2009. 12. 12. 22:16
     

 

<이미지 뷰어와 콘솔 셸이 추가된 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에 이미지 뷰어와 콘솔 셸이 추가된 화면입니다. ㅎㅎ 조만간 또 테스트할 수 있는 바이너리... 보다는 동영상으로 한번 올리겠습니다. ;)


Android App

Posted by 호기심 많은 kkamagui(까마귀, 한승훈)

댓글을 달아 주세요

  1. 여운산 2009.12.13 14:43  댓글주소  수정/삭제  댓글쓰기

    음. 그런데 대부분 커널들이 시스템 콜로는 SYSCALL 보다는 SYSENTER 을 사용하는것 같더군요 (Windows NT 커널을 포함해서).
    그리고 NASM 에서는 REX.W 는 o64 로 명시하실 수 있어요. ex: o64 sysret

    • Favicon of http://www.mint64os.pe.kr BlogIcon kkamagui 2009.12.13 19:58  댓글주소  수정/삭제

      엇~ o64라는 키워드가 있었나요? 좋은 정보 감사합니다. ㅠㅠ 아무리 찾아도 없던데... 역시 검색 능력의 부재였군요. ㅠㅠ

      저도 사실 SYSENTER와 SYSCALL 중에서 고민했었는데, SYSENTER를 호출하면 스택 포인터(RSP)가 바뀌어 버려서 지금 OS의 구조에는 맞지 않더군요. ㅠㅠ 그래서 일단 SYSCALL로 결정했습니다.

      좋은 정보 감사합니다. ;) -b

      ps) o64 키워드는 어떻게 찾으신건가요? NASM 사이트에 있는 메뉴얼을 아무리 뒤져도 없던데... 혹시 찾으신 곳을 좀 알 수 있을까요? ㅎㅎ

    • 여운산 2009.12.14 02:36  댓글주소  수정/삭제

      o64 는 예전에 64비트로의 far jump 코드를 ndisasm 으로 디스어셈블링하다가 우연히 발견했는데 꽤 유용하더군요. lretf 와 같은 인스트럭션은 o64 retf 식으로 필히 명시할 수 밖에 없으니 ..

    • Favicon of http://www.mint64os.pe.kr BlogIcon kkamagui 2009.12.16 07:57  댓글주소  수정/삭제

      엇~ 그러시군요 ;) 제보해 주셔서 감사합니다.
      덕분에 코드가 깔끔해졌어요 ;)

  2. Favicon of http://www.mint64os.pe.kr BlogIcon kkamagui 2009.12.13 19:43  댓글주소  수정/삭제  댓글쓰기

    <STYLE TYPE='text/css'>
    A:link { text-decoration:none; }
    A:visited { text-decoration:none; }
    A:active { text-decoration:none; }
    A:hover { text-decoration:none; }
    </style>

  3. 김상규 2009.12.13 19:53  댓글주소  수정/삭제  댓글쓰기

    음.. SYSENTER가 x64에서 세그먼트가 거의 죽은거나 마찬가지라 안되고 SYSCALL 밖에 안된다고 나와있는거 때문에 사용한건가 봐용 ㅋㅋ 근데 nasm 믿었는데 배신 당하면 ...-ㅅ-;;

  4. 꽈당 2009.12.18 19:47  댓글주소  수정/삭제  댓글쓰기

    오, 또 글이 올라왔네요.
    역시 살아계셨군 후훗

  5. Favicon of https://zelon.tistory.com BlogIcon zelon 2009.12.20 22:51 신고  댓글주소  수정/삭제  댓글쓰기

    내가 직접하지는 않는, 매우 low level 쪽 코딩이지만 이렇게 눈동냥해서 보는 재미도 쏠쏠하네. 언젠가는 나한테도 도움이 되리라 믿으며 ㅎㅎ 늘 잘보고 있어요~ :)

    잘 지내지? ^^ 늘 화이팅~~

    • Favicon of http://www.mint64os.pe.kr BlogIcon kkamagui 2009.12.21 22:02  댓글주소  수정/삭제

      옷~ 횽~ 오래간만이에요 ;)
      저야 뭐 죽을맛(?)이지요 ㅎㅎ
      횽도 잘 지내시죠? 나중에 좀 마무리되면 밥이나 같이 어요 ㅎㅎ ;)