微软公司的一道汇编笔试题,大家来做做!

mengshijie_1981 2007-07-25 03:49:42
array1是一个由32个16进制位组成的无符号整数变量,假设其已经初始化。请试着在32位机器上,将其转换成十进制数,并将转化后结果的ASCII码按从低位到高位的顺序依次存入array2变量中。例如:array2[0]存放个位,array2[1]存放十位,以此类推。因为array2的长度有富裕,要求转化完成后,用EDI存放转化后十进制数最高位在array2数组中的下标。array1和array2的定义如下:
DATAS SEGMENT
array1 DB 16 DUP(0)
array2 DB 50 DUP(0)
DATAS ENDS

题目就是如此,是我的一个朋友给我发过来的,据他说是微软的笔试题,是真是假我没有考证过,但感觉这道题不错,贴出来供大家学习,研究!
...全文
2255 25 打赏 收藏 转发到动态 举报
写回复
用AI写文章
25 条回复
切换为时间正序
请发表友善的回复…
发表回复
lichunpu 2007-07-30
  • 打赏
  • 举报
回复
用C完成的对任意长度的16进制字符串,转10进制字符串。
#include <stdio.h>

static char *array1 = "ffffffffffffffff";

int main()
{
char h[256];
char hh[2] = {0};
char d[256];
char tmp[256];
int i = 0;
int j = 0;
int k = 0;
int len = 0;
unsigned int ui = 0;
unsigned int tt = 0;
int key = 0;

memset(h, 0, 256);
memset(tmp, 0 , 256);
memset(d, 0, 256);
strcpy(tmp, array1);

while(strlen(tmp) > 1 || tmp[0] >= 'A')
{
key = 0;
tt = 0;
j = 0;
memcpy(h, tmp, 256);
memset(tmp, 0 , 256);
len = strlen(h);
for (i = 0; i < len; i++)
{
hh[0] = h[i];
ui = strtoul(hh, NULL, 16) + tt * 16;
if (ui >= 10)
{
if (ui/10 >= 10)
{
tmp[j] = ui/10 - 10 + 'A';
}
else
{
tmp[j] = ui/10 + '0';
}
tt = ui%10;
j++;
key = 1;
}
else
{
tt = ui%10;
if (key == 1)
{
tmp[j] = '0';
j++;
}
}
}
d[k] = tt + '0';
k++;
}
d[k] = tmp[0];

len = strlen(d);
for (i = len - 1; i >= 0; i--)
{
printf("%c", d[i]);
}
printf("\n");

return 0;
}

输出结果:
18446744073709551615
mengshijie_1981 2007-07-27
  • 打赏
  • 举报
回复
kwing() 回帖真是认真呀,佩服!
kwing 2007-07-27
  • 打赏
  • 举报
回复
上面的程序还有点小错误,再次修正:

;假设array1是按字节小端排列的
;没有考虑array1全是0的情况
mov edi,array2
mov ecx,10
@next1:
xor ebx,ebx
xor edx,edx
mov esi,12
@next2:
mov eax,[array1+esi]
div ecx
or ebx,eax
mov [array1+esi],eax
sub esi,4
jns @next2
lea eax,[edx+48]
stosb
test ebx,ebx
jnz @next1
sub edi,array2+1
kwing 2007-07-27
  • 打赏
  • 举报
回复
上面的程序最后edi是地址,不是下标,修正一下:

;假设array1是按字节小端排列的
;没有考虑array1全是0的情况
mov edi,array2
mov ecx,10
@next1:
xor ebx,ebx
xor edx,edx
mov esi,12
@next2:
mov eax,[array1+esi]
div ecx
or ebx,eax
mov [array1+esi],eax
sub esi,4
jns @next2
lea eax,[edi+48]
stosb
test ebx,ebx
jnz @next1
sub edi,array2+1
kwing 2007-07-27
  • 打赏
  • 举报
回复
;假设array1是按字节小端排列的
mov edi,array2
mov ecx,10
@next:
xor ebx,ebx
xor edx,edx
mov eax,[array1+12]
div ecx
or ebx,eax
mov [array1+12],eax
mov eax,[array1+8]
div ecx
or ebx,eax
mov [array1+8],eax
mov eax,[array1+4]
div ecx
or ebx,eax
mov [array1+4],eax
mov eax,[array1]
div ecx
or ebx,eax
mov [array1],eax
lea eax,[edi+48]
stosb
test ebx,ebx
jnz @next
dec edi
奶糖人五号 2007-07-26
  • 打赏
  • 举报
回复
mark
liuqiaohui 2007-07-26
  • 打赏
  • 举报
回复
上面的方法中,被除数放在数组中,余数放在数组中,商放在被除数数组中,每次求得的商当作下一次使用的被除数,每次取得的余数加上30H后依次填入个位,十位……
这个思路应该是最好的办法
mengshijie_1981 2007-07-26
  • 打赏
  • 举报
回复
除十取余问题我已经解决了,说一说思路!

我们在利用汇编编程时,过分的依赖于MUL、DIV等指令的,如此当寄存器不够用时,就难倒了我们,是指令和寄存器束缚了我们的思想,从此我将接受教训。如果除十取余的问题是给一个非计算机专用的人出的问题,他很可能很快的就能想出下面的算法:

0AH /-------------
/ 被除数
商*0AH
--------
余数
而这种算法在我的脑海已经尘封起来了。遇到位数超过寄存器表达范围时,我总是再想移位,加法之类的方法来解决。却忽略了我们所使用过的最原始的方法。上面的方法中,被除数放在数组中,余数放在数组中,商放在被除数数组中,每次求得的商当作下一次使用的被除数,每次取得的余数加上30H后依次填入个位,十位……

有了算法,编程还是问题吗?(如果我们连编程也不会了,那我们就真的成了饭桶了^_^)
mengshijie_1981 2007-07-26
  • 打赏
  • 举报
回复
f 0 f
a1 a2 a3
这就是高阶。
个位其实就是 15+0*6+6*15=105
10位就是0*1+5*15=75
100位2*15=30
30 00
75 0
105
------
3855

上面的代码,我不明白是什么意思?
个位其实就是 15+0*6+6*15=105 ;个位怎么是105,十进制数的个位怎么能够容纳105?
10位就是0*1+5*15=75 ;十位怎么是75,十进制数的十位怎么能够容纳75
100位2*15=30 ;百位应该也只能容纳1位数字,怎么是30呢?

0f0fH转换后是确实是3855
whycadi 2007-07-25
  • 打赏
  • 举报
回复
x86的FPU的FBSTP指令是不是能把FPU里的整数变成BCD数?
如果是的话那,128位的2进制,先用10亿除几次,取余,分成5个32位数,然后把它们一个一个按整形加载到FPU中,再以BCD格式取出来,再拼起来.
hrb52 2007-07-25
  • 打赏
  • 举报
回复
看了上面的算法不知道明白了没有。
其实用汇编,这样算根本不存在溢出的地问题,因为有eax和al,ah的至间的传递。
多数组只是我在极端的情况下假设。实际上,一般的寄存器是够用了。
hrb52 2007-07-25
  • 打赏
  • 举报
回复
其实这道题还是应该用除十取余法,因为这个方法非常奏效,算法简单易行,而且不易出错。问题的关键在于怎么对大数实现除十取余,显然用常规的除法是难以实现的,主要是寄存器位数不够。所以除十取余必须转化为移位运算和加减运算才行。除十取余问题要是解决了,这道题目也就解决了。
--------------------------------------------
f 0 f
a1 a2 a3
这就是高阶。
个位其实就是 15+0*6+6*15=105
10位就是0*1+5*15=75
100位2*15=30
30 00
75 0
105
------
3855
wdqfzy 2007-07-25
  • 打赏
  • 举报
回复
跟俺期末考试的时候题差不多,只是俺学的是8086cpu。
而且也没那两个数组。不会啊
学习中。。。。
wdqfzy 2007-07-25
  • 打赏
  • 举报
回复
学习
mengshijie_1981 2007-07-25
  • 打赏
  • 举报
回复
小端格式,array[0]的低半字节存放着最低的那个十六进制位,高半字节存放着第二个十六进制位,依次类推,高地址存放高位。
  • 打赏
  • 举报
回复
128-bit整数转化为串,难度一般。
但是没说array1是小端格式还是大端格式。
mengshijie_1981 2007-07-25
  • 打赏
  • 举报
回复
大家继续讨论,稍后我会给出完整的代码……
czlyc006 2007-07-25
  • 打赏
  • 举报
回复
同意LZ的观点,16进制转10进制思路其实不是难点,怎样操作数组才是需要考虑的。
mengshijie_1981 2007-07-25
  • 打赏
  • 举报
回复
其实这道题还是应该用除十取余法,因为这个方法非常奏效,算法简单易行,而且不易出错。问题的关键在于怎么对大数实现除十取余,显然用常规的除法是难以实现的,主要是寄存器位数不够。所以除十取余必须转化为移位运算和加减运算才行。除十取余问题要是解决了,这道题目也就解决了。
mengshijie_1981 2007-07-25
  • 打赏
  • 举报
回复
如果要转化的16进制数不超过8个十六进制位,可以将其放入EAX,用除10取余法,商再除10取余依次填充个位,十位百位,……。但是被处理的数远远超出了EAX的表示范围,因此除10取余法不再适用。把问题变得复杂起来,如果寄存器足够长度,那这个问题就不叫问题了!哈哈
加载更多回复(5)

21,458

社区成员

发帖
与我相关
我的任务
社区描述
汇编语言(Assembly Language)是任何一种用于电子计算机、微处理器、微控制器或其他可编程器件的低级语言,亦称为符号语言。
社区管理员
  • 汇编语言
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧