【问题标题】:using atof function in x86 NASM在 x86 NASM 中使用 atof 函数
【发布时间】:2015-11-22 01:53:52
【问题描述】:

我在让 c 函数 atof() 在我的 asm 程序中工作时遇到了一些问题。我正在尝试从键盘读取 4 个数字,并最终打印它们的平均值。然而,在我能做到这一点之前,我需要将数字转换为浮点数。我坚持成功地让我的“总”变量起作用。我尝试在多个地方调用 atof 均无济于事。

这是一个 x86 NASM 程序

;   nasm -f elf -l prg2.lst prg2.asm
;   gcc -o prg2 prg2.o
;   ./prg2

SECTION .DATA

prompt  DB  'enter a test score.', 13,10
fmt DB  "%s",0
fmtf    DB  "%f",0      


SECTION .bss
test1   resb    1000        ;reserves variable names to
test2   resb    1000        ;put stuff in
test3   resb    1000
test4   resb    1000
total   resb    1000


SECTION .code
extern printf
extern scanf
extern atof
global main
main:

push    ebp
mov     ebp, esp

push    prompt
call    printf
add     esp, 4  ;prompt user

push    test1   ;push test1 variable
push    fmt
call    scanf
add esp, 8  ;store test1 variable

push    prompt
call    printf
add     esp, 4  ;prompt user

push    test2   ;push test2 variable
push    fmt
call    scanf
add esp, 8  ;store test2 variable

push    prompt
call    printf
add     esp, 4  ;prompt user

push    test3   ;push test3 variable
push    fmt
call    scanf
add esp, 8  ;store test3 variable

push    prompt
call    printf
add     esp, 4  ;prompt user

push    test4   ;push test4 variable
push    fmt
call    scanf
add esp, 8  ;store test4 variable

mov     eax,[test1]
add     eax,[test2] 
add     eax,[test3] 
add     eax,[test4] 

call    atof
mov     [total], eax

push total
call printf ;not printing what i want, 
add esp,4   ;or printing anything at all

push    test1   ;printing scores for verification
call    printf
add esp, 4  

push    test2
call    printf
add esp, 4

push    test3
call    printf
add esp, 4

push    test4
call    printf
add esp, 4

mov     esp, ebp
pop     ebp

ret

编辑:修改后,我能够使用这些代码块将输入的值转换为各自的数值

mov eax, 0          ;
add eax,[test1]     ;put test1 value in eax
mov [total], eax    
sub eax, '0'        

add eax,[test2]     
mov [total], eax        
sub eax,'0'

add eax,[test3]     
mov [total], eax        
sub eax,'0'

add eax,[test4]     ;
mov [total], eax        
sub eax,'0'

push    total   
call    printf  
add esp, 4  

示例运行:

./prg2b
enter a test score.
1
enter a test score.
1
enter a test score.
1
enter a test score.
1
41111

我的代码中的这个添加消除了我的 atof() 调用问题,但只有当数字为一位且总数为 时才会成功

如果有人能提供有关如何正确使用 atof 或如何在使用 scanf 的程序中正确转换为浮点数的提示,将不胜感激。我对 x86 asm 很陌生(阅读:2 周的学习)。这是在 UNIX 系统的终端中编译的

【问题讨论】:

  • add 是整数加法。它不添加浮点数。我对您的课程材料一无所知,但也许您的教授打算让您使用 x87 浮点指令(或 SSE)?有关使用 x87 在 NASM 中添加浮点数的示例信息可以在这些examples 底部附近的示例中找到
  • 好吧,我想我只是用整数加法来添加它们,但是当我除以平均值时,我会产生一个浮点数。所以我担心将值存储为浮点数
  • 因此您需要阅读“%d”格式说明符才能读取整数。您可以使用add 将整数相加。我建议阅读您的课程材料,其中可能包含有关将整数加载到 FPU 堆栈(在此过程中将其转换为浮点数)等指令的信息。您可以使用 fdiv (fidiv 可能更合适)除以元素的数量。给这只猫剥皮的方法很多。需要了解浮点运算。

标签: assembly floating-point x86 nasm atof


【解决方案1】:

您可以使用反引号在 NASM 中定义带有转义序列的 C 文字。例如。

prompt  DB  `enter a test score.\n`, 0    ; Don't forget the last 0

atof 需要堆栈上的内存地址,并将结果返回到 FPU 的寄存器 ST(0)。您必须先将每个字符串转换为数字,然后才能使用它进行计算。

SECTION .data
    prompt  DB `Enter a test score\n`, 0
    fmt     DB  " %s", 0
    fmtf    DB  `Sum: %f\n`, 0

SECTION .bss
    test1   resb 1000
    test2   resb 1000
    test3   resb 1000
    test4   resb 1000
    double1 resq 1          ; Reserve Quadword = Double
    double2 resq 1
    double3 resq 1
    double4 resq 1
    sum     resq 1

SECTION .code
extern printf, scanf, atof
global main
main:

    push ebp                ; Prolog
    mov ebp, esp

    push prompt             ; `enter a test score\n`
    call printf
    add esp, (1*4)          ; Pop 1 dword
    push test1
    push fmt                ; " %s"
    call scanf
    add esp, (2*4)          ; Pop 2 dwords
    push test1
    call atof
    fstp qword [double1]
    add esp, (1*4)          ; Pop 1 dword

    push prompt             ; `enter a test score\n`
    call printf
    add esp, (1*4)          ; Pop 1 dword
    push test2
    push fmt                ; " %s"
    call scanf
    add esp, (2*4)          ; Pop 2 dwords
    push test2
    call atof
    fstp qword [double2]
    add esp, (1*4)          ; Pop 1 dword

    push prompt             ; `enter a test score\n`
    call printf
    add esp, (1*4)          ; Pop 1 dword
    push test3
    push fmt                ; " %s"
    call scanf
    add esp, (2*4)          ; Pop 2 dwords
    push test3
    call atof
    fstp qword [double3]
    add esp, (1*4)          ; Pop 1 dword

    push prompt             ; `enter a test score\n`
    call printf
    add esp, (1*4)          ; Pop 1 dword
    push test4
    push fmt                ; " %s"
    call scanf
    add esp, (2*4)          ; Pop 2 dwords
    push test4
    call atof
    fstp qword [double4]
    add esp, (1*4)          ; Pop 1 dword

    fld qword [double1]
    fadd qword [double2]
    fadd qword [double3]
    fadd qword [double4]
    fstp qword [sum]

    push dword [sum + 4]    ; Push a double in two steps
    push dword [sum + 0]
    push fmtf               ; `result: %f\n`, 0
    call printf
    add esp, (3*4)          ; Pop 3 dwords

    mov esp, ebp            ; Epilog
    pop ebp
    ret

您不需要atof。可以让scanf将输入的字符串转换为格式字符串“%lf”。

SECTION .data
    prompt  DB `Enter a test score\n`, 0
    fmt     DB  " %lf", 0                   ; scanf needs 'lf' to store a double
    fmtf    DB  `Sum: %f\n`, 0              ; printf needs only 'f' to print a double

SECTION .bss
    double1 resq 1          ; Reserve Quadword = Double
    double2 resq 1
    double3 resq 1
    double4 resq 1
    sum     resq 1

SECTION .code
extern printf, scanf, atof
global main
main:

    push ebp                ; Prolog
    mov ebp, esp

    push prompt             ; `enter a test score\n`
    call printf
    add esp, (1*4)          ; Pop 1 dword
    push double1
    push fmt                ; " %lf"
    call scanf
    add esp, (2*4)          ; Pop 2 dwords

    push prompt             ; `enter a test score\n`
    call printf
    add esp, (1*4)          ; Pop 1 dword
    push double2
    push fmt                ; " %lf"
    call scanf
    add esp, (2*4)          ; Pop 2 dwords

    push prompt             ; `enter a test score\n`
    call printf
    add esp, (1*4)          ; Pop 1 dword
    push double3
    push fmt                ; " %lf"
    call scanf
    add esp, (2*4)          ; Pop 2 dwords

    push prompt             ; `enter a test score\n`
    call printf
    add esp, (1*4)          ; Pop 1 dword
    push double4
    push fmt                ; " %lf"
    call scanf
    add esp, (2*4)          ; Pop 2 dwords

    fld qword [double1]
    fadd qword [double2]
    fadd qword [double3]
    fadd qword [double4]
    fstp qword [sum]

    push dword [sum + 4]    ; Push a double in two steps
    push dword [sum + 0]
    push fmtf               ; `result: %f\n`, 0
    call printf
    add esp, (3*4)          ; Pop 3 dwords

    mov esp, ebp            ; Epilog
    pop ebp
    ret

【讨论】:

  • 那肯定行得通,非常感谢!我希望我可以使用 scanf 将输入存储为浮点数,我只是不知道正确的格式。
猜你喜欢
  • 2012-11-10
  • 2012-02-10
  • 1970-01-01
  • 1970-01-01
  • 2019-07-06
  • 1970-01-01
  • 2015-06-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多