Mac OS X и x86_64

Тема в разделе "WASM.UNIX", создана пользователем Bioworm, 11 окт 2010.

  1. Bioworm

    Bioworm New Member

    Публикаций:
    0
    Регистрация:
    20 янв 2006
    Сообщения:
    7
    Адрес:
    Botswana
    Пара-тройка статеек про ассемблер i386 для Mac OS X такие есть. А что насчет x86_64?

    Я взял "Hello World" для i386 и попробовал превратить его в x86_64.
    Код (Text):
    1. # Hello World x86 asm - MacOS X
    2. # By Erik Wrenholt
    3. # gcc hello.s -o hello ; ./hello ; echo $?
    4.  
    5. # References:
    6. #   http://forums.osxfaq.com/viewtopic.php?t=13976
    7. #   http://www.zathras.de/angelweb/blog-intel-assembler-on-mac-os-x.htm
    8.  
    9. hello:
    10.     .ascii "Hello World!\n"
    11.     len = . - hello
    12.  
    13. .text
    14. .globl _main
    15.  
    16. _syscall:
    17.     int     $0x80   #   call syscall
    18.     ret
    19.  
    20. _main:
    21.     pushl   $len        #   pass the length of the string
    22.     pushl   $hello      #   pass the ptr to the hello string
    23.     pushl   $1          #   pass stdout (1)
    24.     movl    $0x4, %eax  # SYS_write (4)
    25.     call    _syscall
    26.  
    27.     add     $12, %esp   #   clear stack (we pushed 3 args)
    28.     pushl   $0          #   we want to call exit(0), push 0
    29.     movl    $1, %eax    # SYS_exit=1
    30.     call    _syscall
    31.  
    32.     leave
    33.     ret
    Как и следовало ожидать, при попытке сконвертировать этот код возникла куча проблем. Самым нехорошим оказалась смена номеров системных вызовов в 64-битной версии Mac OS X.Частично это победить удалось. Вот что я наваял:
    Код (Text):
    1. .cstring
    2. hello:
    3.         .ascii "Hello World!\n"
    4.         hello_len = . - hello
    5.  
    6. .text
    7. .globl _main
    8.  
    9. _main:
    10.         push $hello_len
    11.         push hello(%rip)
    12.         push $1
    13.         movl $0x02000004,%eax  # SYS_write (4)
    14.         syscall
    15.  
    16. _exit:
    17.         pushq $0
    18.         movl $0x02000001,%eax # SYS_exit (1)
    19.         syscall
    Номера системных вызовов я взял из otool -tV /usr/lib/libSystem.B.dylib. Выход из программы происходит корректно, но она ничего не выводит. Возможно, я неправильно употребил RIP relative addressing и строка push hello(%rip) кладет на стек не совсем то, что я хочу? Или параметры вызова write тоже изменились?

    P.S. И, да, есть ли под Mac OS X нормальный отладчик, где сразу будет видно содержимое регистров и стека, а то GDB как-то не очень информативен?
     
  2. Satsura

    Satsura S4(uR4 __r00tw0rm__

    Публикаций:
    0
    Регистрация:
    22 апр 2010
    Сообщения:
    374
    Адрес:
    Узбекистон, бляать!!11 :D
    >>P.S. И, да, есть ли под Mac OS X нормальный отладчик, где сразу будет видно содержимое регистров и стека, а то GDB как-то не очень информативен?
    - Есть же IDA (дизассм + дебуг) под osX (; А так можете есче посмотреть LLDB. Приведу пример дебуга LLDB и GDB.

    GDB:
    Код (Text):
    1. (gdb) b main
    2. Breakpoint 1 at 0x100000edb: file test.c, line 14.
    3. (gdb) r
    4. Starting program: /private/tmp/a.out
    5. Reading symbols for shared libraries +. done
    6.  
    7. Breakpoint 1, main () at test.c:14
    8. 14 struct i10 v = fun();
    9.  
    10. (gdb) disass main
    11. Dump of assembler code for function main:
    12. 0x0000000100000ed0 : push %rbp
    13. 0x0000000100000ed1 : mov %rsp,%rbp
    14. 0x0000000100000ed4 : sub $0x20000,%rsp
    15. 0x0000000100000edb : lea -0x20000(%rbp),%rdi
    16. 0x0000000100000ee2 : mov $0x0,%eax
    17. 0x0000000100000ee7 : callq 0x100000ea0
    18. 0x0000000100000eec : leaveq
    19. 0x0000000100000eed : retq
    20. End of assembler dump.
    LLDB:
    Код (Text):
    1. (lldb) breakpoint set -n main
    2. Breakpoint created: 1 Breakpoint by name: 'main' with 1 location;
    3. (lldb) r
    4. Launching '/private/tmp/a.out' (x86_64)
    5. (lldb) Process 50271 Stopped
    6. * thread #1: tid = 0x2c03, pc = 0x0000000100000edb, where = a.out`main + 11 at /private/tmp/test.c:14, stop reason = breakpoint 1.1, queue = com.apple.main-thread
    7. 11
    8. 12 int main()
    9. 13 {
    10. 14 -> struct i10 v = fun();
    11. 15 }
    12.  
    13. (lldb) disass
    14. 0x100000ed0: pushq %rbp
    15. 0x100000ed1: movq %rsp, %rbp
    16. 0x100000ed4: subq $131072, %rsp
    17. 0x100000edb: leaq -131072(%rbp), %rdi
    18. 0x100000ee2: movl $0, %eax
    19. 0x100000ee7: callq 0x100000ea0 ; fun at /private/tmp/test.c:7
    20. 0x100000eec: leave
    21. 0x100000eed: ret
     
  3. Bioworm

    Bioworm New Member

    Публикаций:
    0
    Регистрация:
    20 янв 2006
    Сообщения:
    7
    Адрес:
    Botswana
    ОК, все заработало. Оказывается, в Mac OS X в 64-битном режиме то же соглашение вызовов, что и у Linux. (Удивительно -- я же видел упоминание этого на сайте Apple, в упор смотрел, но не верил).

    Код (Text):
    1. .cstring
    2. HelloString:
    3.         .ascii "Hello World!\n"
    4.         HelloStringLen = . - HelloString
    5.  
    6. .text
    7. .globl _main
    8.  
    9. _main:
    10.                 leaq HelloString(%rip), %rsi
    11.                 movq $HelloStringLen, %rdx
    12.                 movq $1,%rdi
    13.                 movl $0x02000004, %eax # SYS_write (4)
    14.                 syscall
    15.  
    16. _exit:
    17.                 xor %rdi, %rdi
    18.                 movl $0x02000001, %eax # SYS_exit (1)
    19.                 syscall
    За наводку на lldb cпасибо.
     
  4. Bioworm

    Bioworm New Member

    Публикаций:
    0
    Регистрация:
    20 янв 2006
    Сообщения:
    7
    Адрес:
    Botswana
    Satsura
    A не подскажете, как в x86_64 закодить что-то вроде mov al, [Label+eax]? Если написать movb Label(%rax), %al, то gas эту строчку не примет, ибо "32-bit absolute addressing is not supported for x86-64". Это значит, сначала надо загружать адрес Label в какой-нибудь регистр, прибавлять к нему содержимое %rax, и только потом вытаскивать байт из этого адреса? Но ведь это получается три команды вместо одной.