에서
감사는 내가 얼마 전에 손 소수점 루틴에서 기본적인 지침을 사용하여/일부 문자열을 쓴 것이다.
그들은 내가 돕고있는 다른 그룹에 대해 이미 주석 처리되었지만 유용하다고 생각할 수도 있습니다.
"strlen"proc은 scasb 등으로 더 빠를 수도 있지만 기본적으로 초보자를위한 교육용 도구이지만 ASM은 물론 모든 작업에 대해 충분히 빠름 인간 상호 작용을 포함한다. 아마도 wsprintf et.al보다 빠릅니다. 단 하나의 경우 (십진수) 만 처리하기 때문입니다.
이들은 정수로만 쓰여지므로 10 진수 문자열 만 출력하면 정수 부분을 02Eh 뒤에 출력하고 소수 부분을 10^SignificantPlaces로 곱하면됩니다. 그것도.
오 BTW
재밌게 = D : 제가 계산을위한 정밀 약간 필요하지만 최종 결과는 정수를 끝나게 많은 분할하는 작업에 대해 다음과 같은 긴 값으로 나는 때로 믿을 함께 일하고 있어요 너무 커서 xxx, 8 또는 shl xxx, 16을 다 쓰고 그 다음 div와 그 밖의 무엇이든 다른 것이 무엇이든지간에 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).
사용자가 직접 텍스트로 변환하거나 사용 가능한 경우 C 라이브러리를 사용해야합니다. – Jester
부동 소수점 결과가 필요하지 않은 경우 정수를 텍스트로 쉽게 변환 할 수 있으므로 정수 나누기 명령어 DIV 및 IDIV를 대신 사용할 수 있습니다. –
@Jester 고마워요, C 라이브러리는 정말 옵션이 아니에요, 나는 그것을 텍스트로 변환하려고 노력할 것입니다. – MarkwinVI