在 x64 程序集中存储键盘输入 (Mac OS/X)
Storing keyboard Input in x64 assembly (Mac OS/X)
一段时间以来,我一直在尝试从键盘获取数字并将其与堆栈中的值进行比较。如果正确,它会打印 "Hello World!",如果不正确,它应该打印 "Nope!"。然而,现在发生的是无论输入 "jne" 是否被调用,nope 是否被打印,以及段错误。也许你们中有人可以伸出援手。
.section __DATA,__data
str:
.asciz "Hello world!\n"
sto:
.asciz "Nope!\n"
.section __TEXT,__text
.globl _main
_main:
push %rbp
mov %rsp,%rbp
sub [=12=]x20, %rsp
movl [=12=]x0, -0x4(%rbp)
movl [=12=]x2, -0x8(%rbp)
movl [=12=]x2000003, %eax
mov [=12=], %edi
subq [=12=]x4, %rsi
movq %rsi, %rcx
syscall
cmp -0x8(%rbp), %edx
je L1
jne L2
xor %rbx, %rbx
xor %rax, %rax
movl [=12=]x2000001, %eax
syscall
L1:
xor %rax, %rax
movl [=12=]x2000004, %eax
movl , %edi
movq str@GOTPCREL(%rip), %rsi
movq , %rdx
syscall
ret
L2:
xor %eax, %eax
movl [=12=]x2000004, %eax
movl , %edi
movq sto@GOTPCREL(%rip), %rsi
movq , %rdx
syscall
ret
我会从这个开始 OS/X Syscall tutorial (The 64-bit part in your case). It is written for NASM syntax but the important information is the text and links for the SYSCALL calling convention. The SYSCALL table is found on this Apple webpage. Additional information on the standard calling convention for 64-bit OS/X can be found in the System V 64-bit ABI。
对 SYSCALL 约定很重要:
- arguments are passed in order via these registers rdi, rsi, rdx, r10, r8 and r9
- syscall number in the rax register
- the call is done via the syscall instruction
- what OS X contributes to the mix is that you have to add 0x20000000 to the syscall number (still have to figure out why)
您的 sys_read
系统调用有很多问题。 SYSCALL table 表示:
3 AUE_NULL ALL { user_ssize_t read(int fd, user_addr_t cbuf, user_size_t nbyte); }
所以给定调用约定,int fd
在RDI中,user_addr_t cbuf
(指向保存return数据的字符缓冲区的指针)是在 RSI 中,user_size_t nbyte
(缓冲区可以包含的最大字节数)在 RDX.
中
您的程序段在 ret
处出错,因为您没有合适的函数结尾来匹配顶部的函数序言:
push %rbp #
mov %rsp,%rbp # Function prologue
你需要在底部进行反向操作,将结果代码设置在RAX中,然后进行ret
。类似于:
mov %rbp,%rsp # \ Function epilogue
pop %rbp # /
xor %eax, %eax # Return value = 0
ret # Return to C runtime which will exit
# gracefully and return to OS
我做了其他小的清理,但试图保持代码的结构相似。您将必须学习更多汇编才能更好地理解设置 RSI 和 sys_read
SYSCALL 地址的代码。你应该试着找一个好的tutorial/book on x86-64 assembly language programming in general。写关于该主题的入门书超出了本答案的范围。
考虑到上述因素,可能更接近您所寻找的代码:
.section __DATA,__data
str:
.asciz "Hello world!\n"
sto:
.asciz "Nope!\n"
.section __TEXT,__text
.globl _main
_main:
push %rbp #
mov %rsp,%rbp # Function prologue
sub [=13=]x20, %rsp # Allocate 32 bytes of space on stack
# for temp local variables
movl [=13=]x2, -4(%rbp) # Number for comparison
# 16-bytes from -20(%rbp) to -5(%rbp)
# for char input buffer
movl [=13=]x2000003, %eax
mov [=13=], %edi # 0 for STDIN
lea -20(%rbp), %rsi # Address of temporary buffer on stack
mov , %edx # Read 16 character maximum
syscall
movb (%rsi), %r10b # RSI = pointer to buffer on stack
# get first byte
subb , %r10b # Convert first character to number 0-9
cmpb -4(%rbp), %r10b # Did we find magic number (2)?
jne L2 # If No exit with error message
L1: # If the magic number matched print
# Hello World
xor %rax, %rax
movl [=13=]x2000004, %eax
movl , %edi
movq str@GOTPCREL(%rip), %rsi
movq , %rdx
syscall
jmp L0 # Jump to exit code
L2: # Print "Nope"
xor %eax, %eax
movl [=13=]x2000004, %eax
movl , %edi
movq sto@GOTPCREL(%rip), %rsi
movq , %rdx
syscall
L0: # Code to exit main
mov %rbp,%rsp # \ Function epilogue
pop %rbp # /
xor %eax, %eax # Return value = 0
ret # Return to C runtime which will exit
# gracefully and return to OS
一段时间以来,我一直在尝试从键盘获取数字并将其与堆栈中的值进行比较。如果正确,它会打印 "Hello World!",如果不正确,它应该打印 "Nope!"。然而,现在发生的是无论输入 "jne" 是否被调用,nope 是否被打印,以及段错误。也许你们中有人可以伸出援手。
.section __DATA,__data
str:
.asciz "Hello world!\n"
sto:
.asciz "Nope!\n"
.section __TEXT,__text
.globl _main
_main:
push %rbp
mov %rsp,%rbp
sub [=12=]x20, %rsp
movl [=12=]x0, -0x4(%rbp)
movl [=12=]x2, -0x8(%rbp)
movl [=12=]x2000003, %eax
mov [=12=], %edi
subq [=12=]x4, %rsi
movq %rsi, %rcx
syscall
cmp -0x8(%rbp), %edx
je L1
jne L2
xor %rbx, %rbx
xor %rax, %rax
movl [=12=]x2000001, %eax
syscall
L1:
xor %rax, %rax
movl [=12=]x2000004, %eax
movl , %edi
movq str@GOTPCREL(%rip), %rsi
movq , %rdx
syscall
ret
L2:
xor %eax, %eax
movl [=12=]x2000004, %eax
movl , %edi
movq sto@GOTPCREL(%rip), %rsi
movq , %rdx
syscall
ret
我会从这个开始 OS/X Syscall tutorial (The 64-bit part in your case). It is written for NASM syntax but the important information is the text and links for the SYSCALL calling convention. The SYSCALL table is found on this Apple webpage. Additional information on the standard calling convention for 64-bit OS/X can be found in the System V 64-bit ABI。
对 SYSCALL 约定很重要:
- arguments are passed in order via these registers rdi, rsi, rdx, r10, r8 and r9
- syscall number in the rax register
- the call is done via the syscall instruction
- what OS X contributes to the mix is that you have to add 0x20000000 to the syscall number (still have to figure out why)
您的 sys_read
系统调用有很多问题。 SYSCALL table 表示:
3 AUE_NULL ALL { user_ssize_t read(int fd, user_addr_t cbuf, user_size_t nbyte); }
所以给定调用约定,int fd
在RDI中,user_addr_t cbuf
(指向保存return数据的字符缓冲区的指针)是在 RSI 中,user_size_t nbyte
(缓冲区可以包含的最大字节数)在 RDX.
您的程序段在 ret
处出错,因为您没有合适的函数结尾来匹配顶部的函数序言:
push %rbp #
mov %rsp,%rbp # Function prologue
你需要在底部进行反向操作,将结果代码设置在RAX中,然后进行ret
。类似于:
mov %rbp,%rsp # \ Function epilogue
pop %rbp # /
xor %eax, %eax # Return value = 0
ret # Return to C runtime which will exit
# gracefully and return to OS
我做了其他小的清理,但试图保持代码的结构相似。您将必须学习更多汇编才能更好地理解设置 RSI 和 sys_read
SYSCALL 地址的代码。你应该试着找一个好的tutorial/book on x86-64 assembly language programming in general。写关于该主题的入门书超出了本答案的范围。
考虑到上述因素,可能更接近您所寻找的代码:
.section __DATA,__data
str:
.asciz "Hello world!\n"
sto:
.asciz "Nope!\n"
.section __TEXT,__text
.globl _main
_main:
push %rbp #
mov %rsp,%rbp # Function prologue
sub [=13=]x20, %rsp # Allocate 32 bytes of space on stack
# for temp local variables
movl [=13=]x2, -4(%rbp) # Number for comparison
# 16-bytes from -20(%rbp) to -5(%rbp)
# for char input buffer
movl [=13=]x2000003, %eax
mov [=13=], %edi # 0 for STDIN
lea -20(%rbp), %rsi # Address of temporary buffer on stack
mov , %edx # Read 16 character maximum
syscall
movb (%rsi), %r10b # RSI = pointer to buffer on stack
# get first byte
subb , %r10b # Convert first character to number 0-9
cmpb -4(%rbp), %r10b # Did we find magic number (2)?
jne L2 # If No exit with error message
L1: # If the magic number matched print
# Hello World
xor %rax, %rax
movl [=13=]x2000004, %eax
movl , %edi
movq str@GOTPCREL(%rip), %rsi
movq , %rdx
syscall
jmp L0 # Jump to exit code
L2: # Print "Nope"
xor %eax, %eax
movl [=13=]x2000004, %eax
movl , %edi
movq sto@GOTPCREL(%rip), %rsi
movq , %rdx
syscall
L0: # Code to exit main
mov %rbp,%rsp # \ Function epilogue
pop %rbp # /
xor %eax, %eax # Return value = 0
ret # Return to C runtime which will exit
# gracefully and return to OS