因此,我正在用C编写一个程序,将类似typescript的语法转换为x86汇编。以下代码:
hello = (x: string, y: string, z: string, a: string) => {
print(x);
print(y);
print(z);
print(a);
return 1;
};
main = (argc: int, argv: Array<string>):int => {
hello("firstn", "secondn", "thirdn", "fourthn");
return 0;
};
被转换为此x86程序集:(不过,我添加了一些评论,以解释发生了什么(
.section .text
.globl _start
_start:
movl %esp, %ebp
call main
movl %eax, %ebx
movl $1, %eax
int $0x80
# a function that takes 4 arguments and prints them usin `print`
.type hello, @function
.globl hello
hello:
pushl %ebp
movl %esp, %ebp
pushl 20(%esp)
call print
addl $4, %esp
pushl 16(%esp)
call print
addl $4, %esp
pushl 12(%esp)
call print
addl $4, %esp
pushl 8(%esp)
call print
addl $4, %esp
pushl $1
jmp return_statement
.type main, @function
.globl main
main:
pushl %ebp
movl %esp, %ebp
subl $8, %esp
subl $12, %esp
movl $0x0, 8(%esp)
movl $0x0a74, 4(%esp)
movl $0x073726966, 0(%esp)
movl %esp, -4(%ebp)
# end of "first"
subl $8, %esp
subl $12, %esp
movl $0x0, 8(%esp)
movl $0x0a646e, 4(%esp)
movl $0x06f636573, 0(%esp)
movl %esp, -8(%ebp)
# end of "second"
subl $8, %esp
subl $12, %esp
movl $0x0, 8(%esp)
movl $0x0a64, 4(%esp)
movl $0x072696874, 0(%esp)
movl %esp, -12(%ebp)
# end of "third"
subl $8, %esp
subl $12, %esp
movl $0x0, 8(%esp)
movl $0x0a6874, 4(%esp)
movl $0x072756f66, 0(%esp)
movl %esp, -16(%ebp)
# end of "fourth"
pushl -4(%ebp) # push string "first"
pushl -8(%ebp) # push string "second"
pushl -12(%ebp) # push string "third"
pushl -16(%ebp) # push string "fourth"
call hello
addl $16, %esp
pushl $0
jmp return_statement
# print function takes one argument to print
# then calls `strlen` on that argument to later be used to write to
# stdout.
.type print, @function
print:
pushl %ebp
movl %esp, %ebp
pushl 8(%esp)
call strlen
addl $4, %esp
movl 8(%esp), %ecx
movl %eax, %edx
movl $4, %eax
movl $1, %ebx
movl %ebp, %esp
popl %ebp
int $0x80
ret
# just a label to jump to when returning out of functions
# instead of re-typing this all the time.
return_statement:
popl %eax
movl %ebp, %esp
popl %ebp
ret
.type strlen, @function
strlen:
pushl %ebp
movl %esp, %ebp
movl $0, %edi
movl 8(%esp), %eax
jmp strlenloop
strlenloop:
movb (%eax, %edi, 1), %cl
cmpb $0, %cl
je strlenend
addl $1, %edi
jmp strlenloop
strlenend:
movl %edi, %eax
movl %ebp, %esp
popl %ebp
ret
然后我使用将其组装成二进制文件
as --32 a.s -o main.o -g -W
ld main.o -o main -m elf_i386
当我执行程序时:
./main
我得到一个奇怪的输出:
firsȁÔÿ܁ÔÿðÔÿÔÿ Ôsecond
third
fourth
如果我只打印3个字符串,一切看起来都很好。
我在这里做错了什么?我花了几个小时试图弄清楚这一点。在这一点上,我几乎把整个胡子都刮掉了。
非常感谢这里的帮助。
谢谢。
我解决了这个问题。
在把我所有的字符串放到堆栈之前,我需要将堆栈的大小调整为(字符串数*4(以适应所有字符串地址。
因此,在这种情况下,解决方案是进行
subl $24, %esp
在按下所有字符串之前。
6 * 4
其中,6
是这种情况下的字符串数。
现在,当我将地址写入堆栈时,它们不会覆盖以前的字符串。