我正在创建一个包含一些简单除法的汇编程序(intel 8086 masm32)。一切都在工作,直到该部门产生一个浮动。
因为当您将浮点数加载到eax寄存器时,它只会返回一个大数字。
为了尝试解决我发现的有关FUP的问题,并使用REAL 4来存储浮点数并且它可以工作 我的问题是如何使用WriteConsoleA WindowsAPI将float REAL 4值输出到控制台? 或者在这种情况下可能有不同的处理浮动的方法?
提前致谢
答案 0 :(得分:0)
幸运的是,我不久前用手只用基本指令给十进制例程写了一些字符串。
他们已经为我正在帮助的其他群体注释了,但您也可能会觉得它们很有用。
所有简单的东西,即" strlen"使用scasb等等,proc可能通常会更快。但它们基本上是初学者的教学辅助工具,但是ASM当然可以很快地完成任何涉及人类交互的任务。可能比wsprintf et.al.更快。因为他们只处理一个案例(十进制)。
它们只是为整数编写的,但是因为你只想输出一个十进制字符串,输出整数部分后跟02Eh然后将小数部分乘以10 ^ SignificantPlaces和也写出来。
玩得开心= D
哦顺便说一句:对于我需要一点精度进行计算的许多除法作业,但最终结果最终是整数,那么只要我使用的值不太大,我发现只需shl xxx,8或shl xxx,16所有内容然后div和其他任何东西直到我得到结果然后只需shr xxx,无论什么,并继续卡车运输;)
可能不适合您当前的项目,但通常是一种有用的方法。
.data?
decbuf db 32 dup(?)
.code
; DECIMAL to/from STRING routines
; Lambchops 2/2017
; ( a boy from AUS )
strlen proc saddr:DWORD ;
; return length of string at saddr
mov eax,saddr
dec eax
@@:
inc eax
cmp byte ptr [eax], 0
jnz @B
sub eax,saddr
ret
strlen endp
mul10 proc val:DWORD,expo:DWORD
; multiply val x10 expo times
push ebx
push ecx
mov eax,val
mov ecx,expo
test ecx,ecx
jz mul10out
@@:
lea ebx,[eax*2]
lea eax,[ebx+eax*8] ; x2 + x8 = x10
loop @B
mul10out:
pop ecx
pop ebx
ret
mul10 endp
isDecChar proc cchar:DWORD
; is the low byte of cchar '0'->'9'?
; zf=true
push eax
mov eax,cchar
mov ah,1
cmp al,'0'
jb @F
cmp al,'9'
ja @F
xor eax,eax
@@:
test eax,eax
pop eax
ret
isDecChar endp
getDecimal proc saddr:DWORD
; get the integer value of the unsigned decimal string at address saddr
;
; ignores any char that is not a decimal digit ** including '.' **
;----------------------------------------------------------------------
LOCAL retval
pushad
; zero return value
mov retval,0
; get src address
mov esi,saddr
; get string length
push esi
call strlen
; zero length string?
test eax,eax
jz getdecout
; add the length to the buffer address
add esi,eax
; esi points to zero terminator so dec
dec esi
; set loop counter to string length
mov ecx,eax
; zero the column number
xor ebx,ebx
@@:
xor edx,edx
; get char in dl
mov dl,[esi]
dec esi
; is the char a decimal digit?
push edx
call isDecChar
; skip anything else
jnz skipBadChar
; char '0'=48 so subtract this to get that char's value
sub edx,48
; multiply by 10^column number
push ebx
push edx
call mul10
; add to return value
add retval,eax
; inc the column number
inc ebx
skipBadChar:
loop @B
getdecout:
popad
mov eax,retval
ret
getDecimal endp
strDecimal proc daddr:DWORD,val:DWORD
;--------------------------------------------------------
; write unsigned integer val as a decimal string at daddr
;--------------------------------------------------------
pushad
mov edi,OFFSET decbuf
mov ebx,10
mov eax,val
; generate the string
;(backwards in decbuf)
@@:
; must clear edx before using div
xor edx,edx
; "div" divides eax by the operand (here ebx=10)
; and leaves the remainder in edx, so the remainder
; becomes our next digit value, and we continue
; until eax=0
div ebx
; add '0' to the remainder to convert
; it to an ASCII char
add dl,48
; write the char to the buffer
mov [edi],dl
; inc the buffer ptr
inc edi
; finished?
test eax,eax
jnz @B
;append a zero terminator
mov BYTE ptr[edi],0
; reverse the string and copy to daddr
; (you can work this out, surely ;)
push OFFSET decbuf
call strlen
mov ecx,eax
add eax,OFFSET decbuf
mov edi,daddr
@@:
dec eax
mov dl,[eax]
mov [edi],dl
inc edi
loop @B
mov BYTE ptr[edi],0
popad
ret
strDecimal endp
; Please Note:
;
; These routines have not been exhaustively tested under all
; conditions but appeared to function correctly for the task
; they were written for ( punting smallish integers to and
; from a bunch of EditText boxes ).