代码之家  ›  专栏  ›  技术社区  ›  Hrodebert

在Nasm中使用c中的printf会导致字符串添加随机的结束行语句

  •  1
  • Hrodebert  · 技术社区  · 1 年前

    今天早上,我试图为我的asm项目制作一个简单的输出库,我意识到每次使用sys调用都是浪费时间,所以我决定使用c中的printf函数使程序自动化,所以我试图在github论坛的帮助下制作一个函数,并向我解释asm的工作原理,然后我想出了这段代码。

    SECTION .data
        endLine db 0Ah, 0
        integer_printf:     db  '%d',   10,0
        float_printf        db  '%f',   10,0
        string_format       db  '%s',   10,0
    
    SECTION .text
        extern printf
    
    printStr:
        ; mov rsi, string please put rsi to have the same value as your string variable (pointer)
        mov rdi,string_format ; mov rdi,printf_format
        call printf
        ret
    
    
    %include '../script.asm'
    %include '../funcio.asm'
    
    extern printf
    
    global main
    
    section .data
        float_point     dq     70.232
        integer_value   dq     33      
        string_value    db     "Hello world!", 0
    
    section .text
    
    main:
        movsd xmm0, [float_point]
        call printFloat
        mov rsi, [integer_value]
        call printInt
    
        mov rsi, string_value
        call printStr
        call printStr
        call printStr
        call printStr
        call printStr
    
        mov rdi, 0
        call exit_program
    

    这段代码被细分为两个文件,出于某种原因,当我打印字符串hello world时,每次调用新的打印函数时,它都会增加新行的数量。 这些是信息: 预期输出:

    33
    Hello world!
    Hello world!
    Hello world!
    Hello world!
    Hello world!
    

    获得的输出:

    70.232000
    33
    Hello world!
    Hello world!
    
    Hello world!
    
    
    Hello world!
    
    
    
    Hello world!
    

    谢谢你的建议!

    2 回复  |  直到 1 年前
        1
  •  2
  •   cHao    1 年前

    RSI和RDI是 呼叫者已保存 在大多数调用约定中,这意味着函数可以随意使用它们而无需保存它们(因为调用者已经这样做了,如果它关心的话)。出于同样的原因,你不必在使用它们之前推送它们,在使用之后弹出它们,其他函数也不必这样做,所以你不能依赖这些寄存器来保留它们的值。

    每次都需要重新加载它们。

        ...
        mov rsi, string_value
        call printStr
        mov rsi, string_value
        call printStr
        mov rsi, string_value
        call printStr
        ...
    
        2
  •  0
  •   Hrodebert    1 年前

    经过一番挖掘,我发现原因是像rsi这样的寄存器是易变的,可能会随着时间的推移而丢失值,这就是为什么每次调用都必须重新设置每个寄存器。

    %include '../script.asm'
    %include '../funcio.asm'
    
    extern printf
    
    global main
    
    section .data
        float_point     dq     70.232
        integer_value   dq     33      
        string_value    db     "Hello world!", 0
    
    section .text
    
    main:
        movsd xmm0, [float_point]
        call printFloat
        mov rsi, [integer_value]
        call printInt
    
        mov rsi, string_value
        call printStr
        mov rsi, string_value
        call printStr
        mov rsi, string_value
        call printStr
        mov rsi, string_value
        call printStr
        mov rsi, string_value
        call printStr
        mov rsi, string_value
    
        mov rdi, 0
        call exit_program