yuchi's Development Home
글 수 201
예전에 어셈블리로 떡 쳐놓은게 64비트 포팅에 상당한 걸림돌이 되고 있다.
어셈코드들을 c코드로 다시 짜고는 있으나, 어쩔수 없이 어셈으로 짰던 코드들은 꽤 골치아팠다.
그 중 하나가 가변인자 처리였다.
엔진의 파일 시스템에서 지원하는 fscanf()함수는 팩킹된 파일인지 일반 파일인지에 따라 자체파싱을 하거나 C런타임 라이브러리의 fscanf()를 호출한다.
팩 파일에서 읽는 경우는 메모리에 읽은 후에 자체적으로 만든 sscanf()로 파싱한다. 뭐 기능상 약간 제약은 있지만 별 탈은 없다.
문제는 c런타임라이브러리의 fscanf()를 사용할 경우다.
전에는 간단하게 어셈코드로 짜서 인자를 쉽게 넘겼다.
그런데 x64에선 인라인 어셈을 허용하지 않는데다 , 어차피 기존 32비트 어셈코드는 쓸 수 없었다. 그래서 순수하게 c로 짜려고 했으나....
C만 가지고는 가변인자를 받은 상태 그대로 넘길 방법이 없었다.
외부에서 받은 가변인자 리스트로 fscanf()를 호출하려면 vfscanf()란 놈을 사용해야한다.
늘상 사용하는 c런타임 라이브러리의 fscanf()도 내부적으로 vfscanf()를 호출하는 것을 확인했다.
문제는 vfscanf()는 시스템 내부에서만 사용하고 유져모드에서 사용할 방법이 없다는 것이다.
핼프를 열심히 뒤져보니 posix에선 표준이지만 윈도우에선 지원하지 않는다는 내용을 찾아볼 수 있었다.
고민고민 끝에 x64,x86모두 어셈으로 짜기로 했다.
x86은 인라인으로 짜도 되니까 간단한데, x64는 masm으로 짜야하니 좀 쉽지 않았다. masm문법에 익숙하지 않은건 둘째치고 이놈을 vs2005.net이랑 연동시키는 것부터가 문제였다.
커스텀 빌드를 수동으로 세팅하는 방법은 알고 있었으나, 운좋게도 2005에선 좀더 쉽게 할 수 있는 방법이 있었다.
빌드 rule파일을 이용하는 것인다.
asm파일의 경우는 이미 ml.exe로 링크되어있다. 하지만 내가 하려는건 x64어셈이니까.
기본적으로 포함된 masm.rule파일을 고쳐서 ml64.exe에 연결시키도록 했다.
그 다음은 x64에서 스택 프레임이 어떻게 잡히는지가 문제였는데 꼬박 하룻동안 고민했다. 문서를 열심히 뒤지고 디스어셈블 하고 삽질 끝에 calling convention과 스택프레임이 대해서 깨달음을 얻었다.
대충 그런 내용인데 결과적으로 얻은 것은 다음과 같다.
1.x64에서 스택 구조
2.x64에서 함수 콜링 컨벤션
3.x64레지스터 사용 규약
4.vs2005.net에서 masm사용하기
참고로...인텔 컴파일러를 사용하면 x64플랫폼에서도 인라인 어셈을 쓸 수 있다. 좀 찜찜한것도 있고 masm은 제대로 익혀보고 싶었으니까 그냥 asm파일로 작성했다.
수학함수 포팅할땐 어쩌면 인텔 컴파일러를 사용할지도 모르겠다.
x64 어셈에 관심있는 분들이 계실까 해서 엔진에 적용하기 전에 테스트한 코드를 첨부했다.
또한 함께 사용한 rule파일도 첨부했다.
masm64.rule 파일을 Microsoft Visual Studio 8\VC\VCProjectDefaults\
폴더에다 넣으면 된다. 그리고 나서 비졀씨에서 asm파일을 불러오면 masm64에 연결하겠냐고 물어볼 것이다.
어셈코드들을 c코드로 다시 짜고는 있으나, 어쩔수 없이 어셈으로 짰던 코드들은 꽤 골치아팠다.
그 중 하나가 가변인자 처리였다.
엔진의 파일 시스템에서 지원하는 fscanf()함수는 팩킹된 파일인지 일반 파일인지에 따라 자체파싱을 하거나 C런타임 라이브러리의 fscanf()를 호출한다.
팩 파일에서 읽는 경우는 메모리에 읽은 후에 자체적으로 만든 sscanf()로 파싱한다. 뭐 기능상 약간 제약은 있지만 별 탈은 없다.
문제는 c런타임라이브러리의 fscanf()를 사용할 경우다.
전에는 간단하게 어셈코드로 짜서 인자를 쉽게 넘겼다.
그런데 x64에선 인라인 어셈을 허용하지 않는데다 , 어차피 기존 32비트 어셈코드는 쓸 수 없었다. 그래서 순수하게 c로 짜려고 했으나....
C만 가지고는 가변인자를 받은 상태 그대로 넘길 방법이 없었다.
외부에서 받은 가변인자 리스트로 fscanf()를 호출하려면 vfscanf()란 놈을 사용해야한다.
늘상 사용하는 c런타임 라이브러리의 fscanf()도 내부적으로 vfscanf()를 호출하는 것을 확인했다.
문제는 vfscanf()는 시스템 내부에서만 사용하고 유져모드에서 사용할 방법이 없다는 것이다.
핼프를 열심히 뒤져보니 posix에선 표준이지만 윈도우에선 지원하지 않는다는 내용을 찾아볼 수 있었다.
고민고민 끝에 x64,x86모두 어셈으로 짜기로 했다.
x86은 인라인으로 짜도 되니까 간단한데, x64는 masm으로 짜야하니 좀 쉽지 않았다. masm문법에 익숙하지 않은건 둘째치고 이놈을 vs2005.net이랑 연동시키는 것부터가 문제였다.
커스텀 빌드를 수동으로 세팅하는 방법은 알고 있었으나, 운좋게도 2005에선 좀더 쉽게 할 수 있는 방법이 있었다.
빌드 rule파일을 이용하는 것인다.
asm파일의 경우는 이미 ml.exe로 링크되어있다. 하지만 내가 하려는건 x64어셈이니까.
기본적으로 포함된 masm.rule파일을 고쳐서 ml64.exe에 연결시키도록 했다.
그 다음은 x64에서 스택 프레임이 어떻게 잡히는지가 문제였는데 꼬박 하룻동안 고민했다. 문서를 열심히 뒤지고 디스어셈블 하고 삽질 끝에 calling convention과 스택프레임이 대해서 깨달음을 얻었다.
대충 그런 내용인데 결과적으로 얻은 것은 다음과 같다.
1.x64에서 스택 구조
2.x64에서 함수 콜링 컨벤션
3.x64레지스터 사용 규약
4.vs2005.net에서 masm사용하기
참고로...인텔 컴파일러를 사용하면 x64플랫폼에서도 인라인 어셈을 쓸 수 있다. 좀 찜찜한것도 있고 masm은 제대로 익혀보고 싶었으니까 그냥 asm파일로 작성했다.
수학함수 포팅할땐 어쩌면 인텔 컴파일러를 사용할지도 모르겠다.
x64 어셈에 관심있는 분들이 계실까 해서 엔진에 적용하기 전에 테스트한 코드를 첨부했다.
또한 함께 사용한 rule파일도 첨부했다.
masm64.rule 파일을 Microsoft Visual Studio 8\VC\VCProjectDefaults\
폴더에다 넣으면 된다. 그리고 나서 비졀씨에서 asm파일을 불러오면 masm64에 연결하겠냐고 물어볼 것이다.
어셈블리코드로 호환성있게 작성하는 방법이 있나요?