我刚从these视频教程开始在linux上自学x86程序集。在早期,它教你如何使用write sys-call打印存储在数据部分中的字符串。是否可以使用write syscall打印存储在堆栈中的字符串。这是我编写的代码尝试并执行此操作似乎不起作用。
.data
abc:
.asciz "ABC"
.text
.globl _start
_start:
pushq %rbp
movq %rsp, %rbp
subq $32, %rsp
leaq -32(%rbp), %rdi
movb $65, (%rdi) #move 'A' on to stack
addq $1, %rdi
movb $66, (%rdi) #move 'B' on to stack
addq $1, %rdi
movb $67, (%rdi) #move 'C' on to stack
addq $1, %rdi
movb $0, (%rdi) #Null terminate
movq $4, %rax #4 is write syscall
movq $1, %rbx #1 for stdout
movq %rsp, %rcx #pointer to ABC string on stack
movq $3, %rdx #length of string
int $0x80
movq $1, %rax #exit syscall
xorq %rbx, %rbx
int $0x80
此程序只运行并退出而不打印ABC,但如果我传递存储在数据段中的字符串,则打印ABC。我做错了什么,或者你不能这样做。任何帮助升值。
答案 0 :(得分:4)
您的系统调用号码似乎已经过时了。
从你使用movq
和“r”寄存器,我猜你正在试用x86-64。看一下/usr/include/asm/unistd_64.h
,我可以看到以下内容:
#define __NR_write 1
#define __NR_stat 4
#define __NR_exit 60
strace
同意我的意见:
$ strace ./abc
execve("./abc", ["./abc"], [/* 43 vars */]) = 0
stat("", NULL) = -1 EFAULT (Bad address)
write(-1698988341, NULL, 3 <unfinished ... exit status 0>
请注意,参数也是关闭的。您还使用错误的寄存器来完成其余参数。 x86-64上的调用约定AFAIK按以下顺序使用以下寄存器:rdi
,rsi
,rdx
,r10
,{{1} },r8
。
也许你正试图在x86-64上按照在i386上完成的方式进行系统调用并期望它是一样的?