2015-10-16 60 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!'仍然無限期地打印。 –