x86汇编,打印4个字符串.奇怪的输出



因此,我正在用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是这种情况下的字符串数。

现在,当我将地址写入堆栈时,它们不会覆盖以前的字符串。

最新更新