我正在为类似C语言构建编译器,并且我试图链接一个基本的" void readString(int,char *)"函数在汇编中实现,汇编由我的编译器生成。
已编译的类似c的文件是
void main () {
char t[20];
readString(7,t); // Read 7 bytes and place them in t buffer
}
编译之后,生成的文件是:out.s文件(注意调用约定是:通过堆栈传递参数。也是整数在这种语言中有2个字节大小):
.$0:
.globl main
main:
pushq %rbp
movq %rsp,%rbp
subq $20,%rsp
.$1:
movw $7,%ax # Push first argument in the stack
pushw %ax
.$2:
leaq -20(%rbp),%rax # Push address of the second arg in the stack
pushq %rax
.$3:
subq $8,%rsp # this is not important, needed for the convention being followed
pushq 16(%rbp) # pushing "access link",
call _readString
addq $26,%rsp # caller clears the "leftovers"
.$4:
.$main_0_11:
movq %rbp,%rsp
popq %rbp
ret
库函数的reads.asm中的代码:
.intel_syntax noprefix
.global _readString
_readString push rbp
mov rbp, rsp
push rdi
push rsi
mov rdi, [rbp+32] # First argument
mov rsi, [rbp+34] # Second Argument
mov rdx, rdi
doRead:
mov byte ptr [rsi], 0x00
xor rax, rax
mov rdi, rax
syscall # read syscall, reads up to $rdx bytes
or rax, rax # nothing read
jz finish #
add rsi, rax #
cmp byte ptr [rsi-1], 0x0a # check if last character read was '\n'
jne addZero #
sub rsi, 1 # if so, replace with '\0'
addZero:
mov byte ptr [rsi], 0x00
finish:
pop rsi
pop rdi
pop rbp
ret
链接/运行遵循
$ gcc -c out.s
$ gcc -c reads.s
$ gcc out.o reads.o
$ ./a.out
[2] Segmentation fault ./a.out
描述调用约定的图片
答案 0 :(得分:1)
好的,正如@David Hoelzer建议我再次检查方式" readString"从堆栈中获取参数,它们按顺序颠倒了!
所以reads.asm的第一行将成为
_readString:
push rbp
mov rbp, rsp
push rdi
push rsi
movzx edi, word ptr [rbp+40] # Get first argument, check comments for more info
mov rsi, [rbp+32] # Second Argument
mov rdx, rdi