использование функции atof в x86 NASM

У меня возникли проблемы с тем, чтобы функция c atof() работала в моей программе asm. Я пытаюсь прочитать 4 числа с клавиатуры и в конечном итоге вывести их среднее значение. Однако, прежде чем я смогу это сделать, мне нужно преобразовать числа в числа с плавающей запятой. Я застрял в том, чтобы успешно заставить мою переменную "total" работать. Я пытался вызвать 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(), но оно успешно только в том случае, если числа представляют собой одну цифру, а общее количество равно ‹10.

Если бы кто-нибудь мог подсказать, как правильно использовать atof или как правильно преобразовать числа с плавающей запятой в программу, использующую scanf, это было бы очень признательно. Я очень новичок (читай: 2 недели обучения) в x86 asm. Это скомпилировано в терминале в системе UNIX.


person pfNbigblue    schedule 22.11.2015    source источник
comment
add — целочисленное сложение. Он не добавляет числа с плавающей запятой. Я ничего не знаю о материалах вашего курса, но, может быть, ваш профессор хотел, чтобы вы использовали инструкции x87 с плавающей запятой (или SSE)? Например, информацию о добавлении чисел с плавающей запятой в NASM с использованием x87 можно найти в примере внизу этих примеры   -  person Michael Petch    schedule 22.11.2015
comment
Ну, я думаю, что я должен просто сложить их, используя целочисленное сложение, но когда я делю на среднее, я должен получить число с плавающей запятой. Поэтому я беспокоился о сохранении значений в виде чисел с плавающей запятой.   -  person pfNbigblue    schedule 22.11.2015
comment
Поэтому вам нужно читать спецификатор формата %d для чтения целых чисел. Вы можете использовать add для сложения целых чисел. Я рекомендую прочитать ваш учебный материал, который, вероятно, включает информацию о таких инструкциях, как fild, для загрузки целого числа в стек FPU (преобразование его в число с плавающей запятой в процессе). Вы можете использовать fdiv (фидив может быть более подходящим), чтобы разделить на количество элементов. Много способов снять шкуру с этой кошки. Необходимо понимание операций с плавающей запятой.   -  person Michael Petch    schedule 22.11.2015


Ответы (1)


Вы можете определить литерал C с escape-последовательностями в NASM, используя обратные кавычки. Например.

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

atof требуется адрес памяти в стеке, и он возвращает результат в регистр ST(0) FPU. Вы должны преобразовать каждую строку в число, прежде чем сможете с ней считать.

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
person rkhb    schedule 22.11.2015
comment
это, безусловно, работает, большое спасибо! Я надеялся, что смогу просто сохранить ввод в виде чисел с плавающей запятой, используя scanf, я просто не знал правильного формата. - person pfNbigblue; 23.11.2015