2015-10-16 54 views
2

我是AT & T汇编的新手,我正在学习使用递减运算符decl创建一个打印Hello world! 5次的程序。%eax不会递减? (ATT汇编)

下面的代码:

.data 

hello: 
    .ascii "Hello world!" 

    .text 
loop: 
    decl %eax 
    leaq hello(%rip), %rdi 
    call _puts 
    jnz  loop 
    leave 
    ret 

.globl _main 
_main: 
    pushq %rbp 
    movq %rsp, %rbp 

    movl $5, %eax 
    jmp  loop 

    movl $0, %eax 

    leave 
    ret 

然而,程序打印Hello world!无限期虽然它没有错误编译,怎么了?

编辑

的建议后:

  1. 变化从%eax%rax
  2. 添加pushpop
  3. 重新排序decq呼叫
  4. callloop代替jmp

这里是生成的代码:

.data 

hello: 
    .asciz "Hello world!" 

    .text 
loop: 
    leaq hello(%rip), %rdi 
    pushq %rax 
    call _puts 
    popq %rax 
    decq %rax 
    jnz  loop 

.globl _main 
_main: 
    pushq %rbp 
    movq %rsp, %rbp 

    movq $5, %rax 
    call loop 

    movq $0, %rax 

    leave 
    ret 
+2

按照常规调用约定,eax不会被'call _puts'保留。你可以用'push eax'和'pop eax'来包围你的'call'。你也应该使用'.asciz'或'.string'来让你的字符串零终止。 – Jester

+0

@Jester 好了,这里是(用于\ n#)新一: # pushl%eax中# 呼叫_puts# popl等EAX%# # 但它返回一个错误: hello.s :45:9:错误:指令需要:不64位模式 推%eax中 ^ hello.s:47:9:错误:指令需要:不64位模式 弹出%eax中 ^ –

+0

哦对不起,它是64位。然后使用'%rax'。 – Jester

回答

0

正如贡献的@Fifoernik和@Jester:

  1. 变化从%eax%rax
  2. 添加pushpop
  3. 重新排序decq呼叫

作为贡献的@rhkb,拼图的最后一块:

  • 插入leaveretloop的最后部分
  • 总之:

    .data 
    
    hello: 
        .asciz "Hello world!" 
    
        .text 
    loop: 
        leaq hello(%rip), %rdi 
        pushq %rax 
        call _puts 
        popq %rax 
        decq %rax 
        jnz  loop 
        movq $0, %rax 
        leave 
        ret 
    
    .globl _main 
    _main: 
        pushq %rbp 
        movq %rsp, %rbp 
    
        movq $5, %rax 
        jmp  loop 
    
    +1

    在__this__解决方案中,使用'jmp loop'更合适。在回答你最初的问题时,我给出的解决方案是使用'call loop'是最好的选择。 – Fifoernik

    2

    这将帮助你:

    • 在64位代码中使用%RAX在EAX%代替。
    • 您不能期望您的call _puts保留%rax。所以pushpop吧。
    • 您不能期望您的call _puts保留标志。因此,在jnz loop之前放置decq %rax即可。

    这里的循环:

    loop: 
        leaq hello(%rip), %rdi 
        pushq %rax 
        call _puts 
        popq %rax 
        decq %rax 
        jnz  loop 
        RET 
    

    添加的建议,​​:

    .globl _main 
    _main: 
        pushq %rbp 
        movq %rsp, %rbp 
        movl $5, %rax 
        CALL loop 
        movl $0, %rax 
        leave 
        ret 
    
    +0

    与@Jester在评论中相同,更改所有这些后,我收到'Segmentation fault:11'我将包含上面编辑的代码。 –

    +0

    你为什么解雇你的程序退出?你为什么不叫'循环'? – Fifoernik

    +0

    上面编辑。现在没有错误发生,但是'Hello world!'仍然无限期地打印。 –