【发布时间】:2024-05-02 13:35:02
【问题描述】:
所以,这是一个烦人的问题: [最后一行包含问题,其余内容是更好理解需求的背景。]
在汇编中,我们可以很容易地使用 printf 函数来显示内容。它会自动将二进制数据正确地转换为字符。
现在,在我的作业中,我需要使用十六进制数字并准确显示 10 个此类数字的总和。 我已经使用代码完成了对 ascii 的分类和转换为十六进制数字(存储在半字节/4 位中):
免责声明:
1) esi 寄存器包含必须保存数字的内存位置。
2) temp 是一个 5 字节的缓冲区,最多可以输入 4 个字符。
in: ; loop to take one multidigit input
mov ebx, 1 ;set error flag
scan temp, 5 ;take input
mov ecx, [temp]
mov edi, 4 ;assumes 4 digit input, works for 0 to 4 digit input
test: ;a validation check for input!!
cmp cl, 0Dh ;if current byte contains '\r'
je hop ;skip it
test0:
cmp cl, 030H ;cl >= '0'
jge test9 ;if yes, check if cl is digit
xor ebx, ebx ;otherwise, set error signal
jmp cont
test9:
cmp cl, 039h ;cl <= '9'
jle cont ;if yes, cl is a digit, case closed
jmp test10c ;otherwise, check if cl has hex character
test10c: ;for caps 'A'
cmp cl, 041h ;cl >= 10 (in caps char hex)
jge test15c ;if yes, check if cl is a caps hex character
xor ebx, ebx ;otherwise, set error signal
jmp cont
test15c:
cmp cl, 046h ;cl <= 15 (in hex)
jle conv ;if yes, cl is a caps hex character, case closed
jmp test10s ;otherwise check if cl has small hex character
test10s:
cmp cl, 061h ;cl >= 10 (in small char hex)
jge test15s ;if yes, check if cl is a small hex character
xor ebx, ebx ;otherwise, set error signal
jmp cont
test15s:
cmp cl, 066h ;cl <= 15 (in small char hex)
jle cont ;if yes, cl is a small hex character, case closed
xor ebx, ebx ;otherwise, set error signal
cont:
cmp ebx, 1 ;check for error
jne err ;if error, jump to err (abort loop)
jmp hop ;otherwise continue to next ascii character entered
hop:
rol ecx, 8 ;roll next character into cl
dec edi ;there are only 4 roll-in operations until you repeat the number
jnz test ;loop back to testing
end:
mov dword[temp], ecx ;store number between call
call conv ;convert number
mov ecx, [temp] ;take converted number
mov dword[esi], ecx ;store it in array
mov dword[temp], 0 ;store success signal
jmp quit
err:
mov dword[temp], 0FFh ;store error signal
quit: ;return to caller
ret
conv: ; loop to convert one multidigit input to specific format
mov ecx, dword[temp] ;take number
mov edi, 4 ;set number of rotations
fix:
cmp cl, 0Dh ;check with '\r'
mov cl, 0 ;'\r' will be stored as 0, the numbers 0-15 will be stored as 1-16
jmp skip
cmp cl, 046h ;check with 'F'
jle digitize ;if less, convert caps character to digit
sub cl, 020h ;if more, convert small character to caps
digitize:
cmp cl, 039h ;check with '9'
jle norm ;if less, convert ascii digit to normal digit
sub cl, 07h ;if more, convert character to ascii digit
norm:
sub cl, 030h ;convert ascii digit to hex digit
add cl, 01h ;encode 0-15 as 1-16 to accomodate '\r'
skip:
rol ecx, 8 ;roll next character into cl
dec edi ;there are only 4 roll-in operations until you repeat the number
jnz fix
ret
这里是以特定方式对数字进行编码。您可能会建议以其他方式增加加法算法的简单性。
最后,引用问题:
"你如何使用 sys_write(function no. 4) 将这些编码数字的总和正确写入 stdout(文件描述符 1)?"
【问题讨论】:
-
如果我希望将 100d 转换为十六进制,我会使用计算器......另一种方式,6 余数 4。我将余数存储在数组中最后一个可用位置,然后检查结果是否大于 15。如果是,请重复。如果没有,请将 6 放入阵列的倒数第二个位置。你知道,标准的基本转换的东西。要跟踪的重要事项是 (a) 您输出的位数(这样您就知道从哪里开始显示数组的内容)(b) 大于 9 的数字是 AF
-
如果您可以使用前导零,请从总和的最高有效半字节开始,隔离这 4 位并转换为十六进制字符 (
'0'..'F'),将其打印或添加到缓冲区,然后继续下一个半字节。当您处理完所有 8 个半字节(或 4 个、或 2 个或其他)时停止。如果您不想要任何前导零,则必须首先扫描最重要的非零半字节。 -
嘿,感谢您的评论。您看,这些数字将存储为最多 4 位十六进制数。因此,最大总和将为 0F0F0F0F + 0F0F0F0F = F0F0F0F0 单个字节结果的三位可显示数字。因此,这种情况会产生逻辑错误。该程序实际上旨在运行总和小于 0F0F0F0F 或小于 252645135 的十进制数的总和(比如 N 个)@enhzflep
-
嘿,谢谢你的评论。你能帮我写下那个算法吗?我不太明白你是如何做到这一点的......@Michael
-
这只是一个循环,每次迭代 ROL 4 位,然后使用按位与隔离要处理的 4 位。