我正在为一种类似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
描绘通话约定的图片
好的,正如@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
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句