<이미지 뷰어와 콘솔 셸이 추가된 MINT64 OS>

 오늘 너무 황당한 일이 있어서 오랜 적막(?)을 깨고 한자 적어 올립니다(사실 다시 삽질 안 하려고 잊기 전에 올리는 것이지만... ㅡ_ㅡ;;;). 요즘 유저 레벨 응용 프로그램을 추가하려고 시스템 콜 부분을 구현하고 있는데, 인터럽트나 콜 게이트 방식 말고 다른 방식이 아닌 새로운 방식을 한번 도입해봤습니다. 이미 이 글의 제목에도 나와있지만 SYSCALL과 SYSRET 명령어를 사용하는 것이지요.;)


SYSCALL과 SYSRET 명령어는 INTEL과 AMD 양쪽에서 모두 사용할 수 있으며, IA-32e 모드에서 Ring 0와 Ring 3을 순식간에 오가는데 아주 유용하....다고 적혀있습니다. ㅡ_ㅡa... 실제로 얼마나 빠른지는 잘 모르겠지만 콜 게이트나 인터럽트처럼 스택에 데이터를 저장하고 특권 레벨을 체크하는 부분이 없으므로, 이전 것들(?)보다는 빠를 듯 합니다. ^^;;;;


뭐, 일단 SYSCALL과 SYSRET 명령어를 사용하려면 어떻게 환경을 설정해야 하는지는 INTEL 문서 Volume 3에 4.8.8 부분에 잘 나와있으니 생략하고... 실제로 SYSCALL과 SYSRET를 NASM으로 사용할 때 주의할 점만 한 줄로 정리해보면 다음과 같습니다.


IA-32e 모드의 64bit 서브 모드를 사용할 경우
SYSRET 명령어 앞에 REX.W 비트를 반드시 명시적으로 켜줘야 한다.


위의 사실을 찾는 데만 무려 3시간이 걸렸습니다. ㅠㅠ INTEL 문서를 보면 SYSRET의 경우 IA-32e 모드의 서브 모드 중에서 호환 모드(Compatibility Mode)와 64 비트 모드 중에서 선택해서 돌아갈 수 있으며, 그 핵심은 REX.W 비트라고 적혀있습니다. MINT64 OS는 64비트 서브 모드를 사용하니 REX.W 비트를 켜줘야 하는데, REX.W 비트가 켜지지 않아서 시스템 콜을 호출하고 돌아올 때 문제가 계속 생겼습니다.


코드를 생성할 때 64bit로 생성했기 때문에 NASM이 알아서 붙여 줄거라 생각했는데... 확인 결과 아무것도 없이 그냥 SYSRET 커맨드만 덩그러니 있었습니다. 그래서 시스템 콜을 호출한 뒤에 돌아오면... 잘못된 명령어라는 예외가 발생하더군요. ㅠㅠ 그래서 REX.W 비트를 키려고 봤더니... 


얼래... NASM에는 SYSRET 명령어 앞에 REX.W 비트를 명시적으로 붙이는 접두사나 키워드가 없었습니다~!!! (여운산님이 o64 키워드가 있다는 사실을 제보해주셨습니다. o64 키워드를 붙이니까 잘 되더군요 >ㅁ<)-b 완전 감사합니다). ㅠㅠ 오퍼랜드가 있는 다른 명령어들은 뒤에 오는 오퍼랜드의 크기에 따라 REX.W 비트를 켜주는 모양이던데, SYSRET는 오퍼랜드가 없으니 그냥 넘어간 모양입니다. ㅠㅠ 그래서 아래처럼 설정해줬습니다.


DB 0x48  <== REX Prefix로 W 비트가 1로 설정된 상태입니다. ^^;;;; (제가 해결한 무식한 방법입니다)
SYSRET

o64  <== REX.W 비트를 1로 설정하는 키워드 입니다. ;) (여운산님이 제보해주신 방법입니다, 아주 깔끔하네요 ;) )
SYSRET


이걸 해놓고 나니까 겨우 정상적으로 동작하네요. 이제야 겨우 유저 레벨 코드를 작업할 수 있게 되었습니다. ㅠㅠ)-b 안 그래도 할 일이 산더미 같은데... 이런 일로 시간 낭비(?)를 하고 나니 머리가 어찔하네요. ㅠㅠ 에휴... 이제 다시 작업하러 가야겠습니다.


ps) 위의 화면은 MINT64 OS에 이미지 뷰어와 콘솔 셸이 추가된 화면입니다. ㅎㅎ 조만간 또 테스트할 수 있는 바이너리... 보다는 동영상으로 한번 올리겠습니다. ;)

+ Recent posts