我遇到一个程序集任务问题 - 我需要将简单数字(带逗号)输入转换为32位浮点表示并将其打印为四位十六进制数字。
感谢。
答案 0 :(得分:4)
以下是NASM语法的快速示例。
我使用了SSE XMMx寄存器和函数,因为它们比x87 FPU指令更清晰,更现代。你还提到处理器是64位,所以它应该是兼容/兼容的。
您可以在ideone.com上在线阅读该程序
阅读评论并尝试学习。
global _start
section .data
ten dq 10.0
one dq 1.0
zero dq 0.0
negate dq 8000000000000000h
result dd 0.0
hex db '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
length dd 0
buffer db 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0
section .text
_start:
;;
;; read the fp number from stdin
;;
mov ecx, buffer
mov edx, 32
call read
mov dword [length], eax
movq xmm0, qword [zero]
movq xmm1, qword [zero]
movq xmm2, qword [ten]
movq xmm4, qword [ten]
;;
;; loop through 1 character at a time
;;
mov ebx, dword [length]
test ebx, ebx
jz quit ;; there's no input
mov ecx, 0 ;; offset counter
mov edx, 0 ;; 0 for before decimal, 1 for after decimal
mov edi, 0 ;; 0 for positive, 1 for negative
mov esi, buffer
cmp byte [esi], '-'
jne process
mov edi, 1 ;; the number is negative
inc ecx
process:
movzx eax, byte [esi + ecx]
cmp al, '.' ;; does al contain a decimal point '.'
jne next_check
test edx, edx ;; more than 1 decimal error
jnz quit
mov edx, 1
jmp continue_process
next_check:
sub eax, '0' ;; ascii digit to binary
js end_process ;; not a digit since eax is negative
cmp eax, 10
jge end_process ;; not a digit since eax is >= 10
test edx, edx ;; before or after decimal
jnz mantissa_process
mulsd xmm0, xmm2 ;; result characteristic * 10
cvtsi2sd xmm3, eax
addsd xmm0, xmm3 ;; result characteristic + next digit
jmp continue_process
mantissa_process:
cvtsi2sd xmm3, eax
divsd xmm3, xmm2 ;; next digit / current mantissa power of 10
addsd xmm1, xmm3 ;; result mantissa + next fraction
mulsd xmm2, xmm4 ;; mantissa power * 10
continue_process:
inc ecx
cmp ecx, ebx
jl process
end_process:
addsd xmm0, xmm1 ;; characteristic + mantissa
test edi, edi ;; is the number supposed to be negative ?
jz store_result
movq xmm3, qword [negate]
por xmm0, xmm3 ;; toggle the sign bit
store_result:
cvtsd2ss xmm0, xmm0 ;; double (64bit) to single (32) fp
movd eax, xmm0
mov dword[result], eax
;;
;; convert result to hex
;;
to_hex:
mov edi, buffer
mov esi, hex
mov ebx, 0
mov eax, dword [result]
mov bl, al
and bl, 0fh
mov bl, byte [esi + ebx]
mov byte [edi + 7], bl
shr eax, 4
mov bl, al
and bl, 0fh
mov bl, byte [esi + ebx]
mov byte [edi + 6], bl
shr eax, 4
mov bl, al
and bl, 0fh
mov bl, byte [esi + ebx]
mov byte [edi + 5], bl
shr eax, 4
mov bl, al
and bl, 0fh
mov bl, byte [esi + ebx]
mov byte [edi + 4], bl
shr eax, 4
mov bl, al
and bl, 0fh
mov bl, byte [esi + ebx]
mov byte [edi + 3], bl
shr eax, 4
mov bl, al
and bl, 0fh
mov bl, byte [esi + ebx]
mov byte [edi + 2], bl
shr eax, 4
mov bl, al
and bl, 0fh
mov bl, byte [esi + ebx]
mov byte [edi + 1], bl
shr eax, 4
mov bl, al
and bl, 0fh
mov bl, byte [esi + ebx]
mov byte [edi + 0], bl
;;
;; print result
;;
print_dword:
mov ecx, buffer
mov edx, 8
call write
;;
;; quit
;;
quit:
call exit
exit:
mov eax, 01h ; exit()
xor ebx, ebx ; errno
int 80h
read:
mov eax, 03h ; read()
mov ebx, 00h ; stdin
int 80h
ret
write:
mov eax, 04h ; write()
mov ebx, 01h ; stdout
int 80h
ret