汇编语言将十进制字符串转为十六进制

汇编语言将十进制字符串转为十六进制

Author:Em1ya
发

Part1:Str to hex

基本思路:将10进制字符串的每一个字符提出,减去0x30转化位该位对应的数值,将数值与原结果*10相加
例如:1234的分解成为1+0*10=1,2+1*10=12,3+12*10=123,4+123*10=1234,在加完之后存入寄存器,就自动变成十六进制数

Part2:hex to Str

对于1步骤后的00000064,我们做如下处理
先将该数右移至最低的十六进制位为我们想要提取的位
所以,对于倒数第i项(i从0开始),应右移该寄存器4*i次
比如00000064的“6”那一位
向右移动4二进制位得到00000006
再对该数进行与0xf的操作,只保留最后一位
例如00101011&0xf
就是00001011只保留了最后一个十六进制位
若该位小于等于9,则ADD 30h,
若否,则加上57h(10+57h=87+10=97=ASCII a)

Part3:更好的优化

题目中*10的计算应该如何实现,可以参考lea的实现方式(猜想)
eax*10=eax*8+eax*2=eax<<3+eax<<1
如此可以大量减少运算时间,毕竟一次MUL或者DIV要消耗十分多的时钟周期

Part4:Code

.386
.model flat, stdcall
.stack 4096
option casemap:none
include D:\masm32\include\windows.inc
include D:\masm32\include\kernel32.inc
include D:\masm32\include\masm32.inc
includelib D:\masm32\lib\kernel32.lib
includelib D:\masm32\lib\masm32.lib
ExitProcess PROTO, dwEXITCODE: DWORD
;define your type here
.data
buf byte 20 DUP(0)
w   byte "Please input",0
var DWORD 0  
res BYTE 8 DUP(30h)
.code
main PROC
	INVOKE StdOut, addr w
    INVOKE StdIn,addr buf,20
	MOV edx,0h
	MOV ecx,0h
        ;ecx用来记录你在处理第几个数字
	MOV eax,0h
        ;eax用来存放每一次计算的结果
L2:
	MOV dl,byte PTR [buf+ecx]
        ;把第ecx个字符移到edx的低8位
	CMP dl,0h
        ;看有没有到字符串末尾(ASCII 0)
	JE L1
        ;有就跳出
	SUB dl,30h
        ;没有的话把ASCII值变为数值
	MOV ebx,eax
        ;把结果数值移到ebx来等待处理*10,向左移动3位相当于*8,移1位相当于*2,加起来相当于*10
	SHL ebx,3
	SHL eax,1
	ADD eax,ebx
        ;*10完成,接下来把存在edx里的那一位拿过来加上 
	ADD eax,edx
        ;过程为“100->1+0*10=1->1*10+0=10->10*10+0=100!
	INC ecx
        ;取下一个字符
	JMP L2
L1:
    MOV var,eax
        ;保存十六进制值
	MOV edx,7h
	    ;找每次要处理的字符
	MOV ecx,0h
	    ;记录要第几位
L4:
        MOV eax,var
	MOV ebx,ecx
	SHL ebx,2
	    ;记录位移多少次,因为十六进制一位是四个二进制位,所以左移两次相当于*4
L6:
	CMP ebx,0
        ;位移0次直接进行下一过程
	JE L5
	SHR eax,1
	DEC EBX
	JMP L6
        ;这一过程相当于第一次位移0次,最后一个十六进制为4,第二次移动4位,最后一十六进制位为6
L5:
	AND eax,0fh
	CMP eax,9h
        ;判断是数字还是字母
	JLE L7
	ADD eax,57h
	JMP L8
L7:
	ADD eax,30h
L8:
	MOV [res+edx],al
	INC ecx
	CMP edx,0h
	JE L3
	DEC edx
	JMP L4
L3:
	INVOKE StdOut, addr res
	INVOKE ExitProcess,0
main ENDP
END main

在这里插入图片描述

Part5:总结

要善于利用位运算的优势,对寄存器和内存进行快速操作

十进制换成字符串的过程需要用到除法和取模运算,这在汇编语言中可以通过使用指令实现。 下面是一个将十进制换成字符串汇编语言程序示例: ``` ; 将十进制换成字符串,存储在 buf 中 ; 参数: ; edx = 十进制数 ; ecx = buf 地址 ; 返回值: ; eax = 换后字符串的长度 section .data digits db "0123456789" section .text global dec_to_str dec_to_str: push ebp mov ebp, esp push ebx push esi push edi mov ebx, ecx ; ebx = buf 地址 mov edi, ebx ; edi = 字符串指针 mov esi, edx ; esi = 十进制数 xor eax, eax ; eax = 0 cmp esi, 0 jge .loop_start ; 如果是正数则直接跳到循环开始 mov byte [edi], '-' inc edi neg esi ; 取绝对值 inc eax .loop_start: cmp esi, 0 jz .loop_end ; 如果已经处理完了则跳到结束 xor edx, edx div dword 10 ; edx = 余数,eax = 商 mov dl, byte [digits + eax] ; 将数字换成字符 mov byte [edi], dl ; 存储字符 inc edi inc eax ; 字符串长度加一 jmp .loop_start .loop_end: mov byte [edi], 0 ; 字符串末尾添加 NULL 结束符 sub edi, ebx ; 计算字符串长度 mov eax, edi pop edi pop esi pop ebx mov esp, ebp pop ebp ret ``` 该程序使用了除法指令 `div` 和取模指令 `mod` 来实现将十进制换成字符串的过程。具体来说,程序将十进制数不断地除以 10,将商换成字符并存储到字符串中,直到商为 0。同时,程序还需要处理负数的情况,将负数换成绝对值后,在字符串前添加负号。最后,程序需要加上 NULL 结束符,并计算字符串的长度。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值