我正在寻找一个程序,它将1和1的字符串转换为汇编中的十六进制字符串,其中二进制字符串来自我写入的代码' C&#39 ;.
例如:
10111111100-> "5 F C"
问题是,对于超过12个字符输入,输出是错误的,我的任务最多需要32个字符。
例如给定110010101111-> " CAF"它工作正常! 但是给予10010001101000101011001111000应该是" 12345678" 但我只得到" 123" 使用gdb工具调试我发现值正在被覆盖。如何在代码中进行最小的更改来解决这个问题?感谢
这个想法是将ecx指向的字符串转换为eax中的值。 现在我想每次最右边4个并转换它们,然后把它们放在edx中。
到目前为止,我有:
section .rodata
LC0:
DB "The result is: %s", 10, 0 ; Format string
section .bss
LC1:
RESB 32
section .text
align 16
global my_func
extern printf
my_func:
push ebp
mov ebp, esp ; Entry code - set up ebp and esp
pusha ; Save registers
mov ecx, dword [ebp+8] ; Get argument (pointer to string)
mov ebx, 0 ; counter for length
mov eax, 0 ; will hold the string as a value
mov edx, 0 ; manipulation helper
mov edi, 0 ; counter for ehile_length loop
length:
inc ebx
cmp byte [ecx+ebx], 0x00
jne length
dec ebx
;;;;THIS PART IS PARSING THE STRING INTO A REGISTER;;;
bring_ecx_to_end:
inc ecx
cmp byte [ecx], 0x0
JNE bring_ecx_to_end
dec ecx
dec ecx
or edi ,ebx
add esi,1
while_length:
mov dl,byte [ecx] ; gets 1 char into edx
cmp DL, 0x31 ; the right character
JE inc1 ; if it a '1'
resume_loop:
shl esi,1 ; multiply by 2
dec ecx
sub edi,1
cmp edi,0
jne while_length
;;;;;;;;;;NOW EAX CONSISTS THE STRING ;;;;;;;;;;;;;;
mov dword edx,0 ;target register
while:
mov dword edi ,0
add edi ,15 ; masking
and edi,eax
cmp di , 10
jl less_than_10
;less_than_F
add di ,55
jmp resume
less_than_10:
add di ,48
resume:
or edx,edi
shl edx,8
shr eax,4
cmp al ,0
jne while
shr edx , 8
;;;;;;;;;DONE;;;;;;;;;;;;;
end:
mov dword [LC1],edx
push LC1 ; Call printf with 2 arguments: pointer to str
push LC0 ; and pointer to format string.
call printf
add esp, 8 ; Clean up stack after call
popa ; Restore registers
mov esp, ebp ; Function exit code
pop ebp
ret
inc1:
or eax, esi
jmp resume_loop
答案 0 :(得分:2)
如果要将字符串的零和1转换为字符串的十六进制字符(" 10111111100" - >&#34) ; 000005FC")那么首先要做的是将源字符串的值放在寄存器中。 您需要设置ECX以指向字符串 LC1 。
mov ecx,[ebp+8] ;Pointer to an ASCIIZ string of zero and one characters.
xor ebx,ebx
First:
rcl ebx,1
mov al,[ecx]
inc ecx
shr al,1
jnz First
mov ecx,LC1 ;Buffer to recieve 8 hexcharacters.
Again:
rol ebx,4
您可以将代码shl al,4
shr al,4
简化为and al,15
。
end:
shr ebx, 4
inc ecx ; increment pointer
cmp byte [ecx], 0 ; check if byte pointed to is zero
jnz while_ebx_not_zero ; keep looping until it is null
end 部分不应更改EBX并精确跳回8次。
end:
inc ecx
cmp ecx,LC1+8
jb Again
答案 1 :(得分:2)
语法,陷阱。 (地球上的每个人都做了这件事,包括我在内的数十万次。)
cmp al , 00001001 ;This is actually one thousand and one
jz case1001to9 ;but you treat it like it's nine
我无法判断你是否正在使用 Masm / Tasm / Nasm / 或其他什么,但我相信如果你把这封信放在" {{1} }"在二进制数字的末尾,Masm将识别它们。
(ooops,编辑:最后的字母b
是旧学校。只需检查微软网站上的HERE和新的改进(不,它不是,但我不是&# 39; t得投票)这样做的方法是插入" B
"作为前缀,而不是我最初建议的" {{1} }"作为后缀。)
说出我的话:在你这样做之前,先查看汇编程序的输出,看看0y
实际上是9还是千分之一。
如果您无法在汇编程序中看到输出,请通过调试进行操作。
答案 2 :(得分:1)
任意长度输入的另一种变体。代码是16位的,可能会稍微优化一下。写在膝盖上,以显示想法
mov si, input_string
mov di, output_string
mov ax, 7 ;input_string length
call bin2hex
bin2hex:
add si, ax ;si points to the end of input string
mov bx, ax
mov cx, 4 ;\
div cl ;
cmp ah, 0 ;compute how many nibbles to convert
jz short .a ;and point di to the end of the result buffer
inc di ;
mov ah, 0 ;
.a: ;
add di, ax ;/
mov [di], ah ;terminating zero
.next_nibble:
mov cl, 4 ;iterate 4 times
mov dl, 0
.next_bit:
dec si
mov al, [si]
shr al, 1 ;mov bit0 to carry flag
rcl dl, 1 ;shift with carry flag into the least-significant bit
dec bx
jz short .stop ;end of input string?
dec cx
jnz short .next_bit
.stop:
shl dl, cl ;complete last nibble to full
cmp dl, 0x0a
jl short .to_ascii
add dl, 7 ;0Ah - 0Fh = ASCII codes 41h - 46h
.to_ascii:
add dl, 0x30
dec di
mov [di], dl
test bx, bx ;end of input string reached?
jnz .next_nibble ;continue if not
ret