【发布时间】:2016-02-23 16:39:12
【问题描述】:
我正在用汇编写作,技术上是 HLA(高级汇编),但我在分配作业时遇到了麻烦。这是作业:
编写一个 HLA 汇编语言程序,用于计算圣莫尼卡学院的学生入学费用。 (由于我们只知道如何处理整数运算,我们的程序会稍微不准确)。截至 2014 年秋季,居民的注册费为 46 美元/单元,所有其他人的注册费为 335 美元/单元。冬季或夏季的学生服务费为 48 美元,秋季或春季为 51 美元。停车贴花的购买是可选的,秋季/春季价格为 85 美元,冬季/夏季价格为 45 美元。
将根据用户输入的单个 8 位值输入注册费。费用的格式为:prsseeee,其中 ss 是对应学期的两位值(秋季为 00,冬季为 01,春季为 10 或夏季为 11),eeee 是与数字对应的四位值在注册单位中,r 是对应于学生是否是加利福尼亚居民的单个位,p 是对应于是否需要停车贴花的单个位。该位域的格式如下图:
费用打包位字段 由于只输入了 8 位,因此您的程序应该会读取 2 个十六进制数字。
以下是一些演示这些想法的示例程序对话。 (提示:一点一点地做这个。有很多...) (进一步提示:此任务最重要的部分是使用用户输入的打包数据字段,从中提取子部分。英特尔寄存器的重叠设计可帮助您解析此类数据字段,并且您可以移动位以将正确的部分转换为 BH 或 BL,例如...) (进一步提示:您可以通过直接读取寄存器来读取十六进制数字。) (最后提示:由于我们还没有学会如何做乘法,虽然它有点痛苦,但我希望你会通过一组循环的加法指令来执行乘法)
喂我(2 个十六进制数字,带有 prsseeee 位):CC
秋季学期
12 个单位
加州居民
停车场
总费用 = 688 美元
喂我(2 个十六进制数字,带有 prsseeee 位):4C
秋季学期
12 个单位
加州居民
禁止停车
总费用 = 603 美元
喂我(2 个十六进制数字,带有 prsseeee 位):8C
秋季学期
12 个单位
非居民
停车场
总费用 = 4156 美元
喂我(2 个十六进制数字,带有 prsseeee 位):0C
秋季学期
12 个单位
非居民
禁止停车
总费用 = 4071 美元
喂我(2 个十六进制数字,带有 prsseeee 位):D1
冬季学期
1个单位
加州居民
停车场
总费用 = 139 美元
喂我(2 个十六进制数字,带有 prsseeee 位):91
冬季学期
1个单位
非居民
停车场
总费用 = 428 美元
这是我的代码:
program SMCFee;
#include( "stdlib.hhf" );
static
total : int32 := 0;
begin SMCFee;
stdout.put("Feed me(2 hex digits with the bits prsseeee):");
stdin.get(BL);
mov(total,EAX);
mov(BL,AL);
shr(4,AL);
and( %0000_0011, AL );
cmp(AL, 00);
je Fall;
cmp(AL, 10);
je Spring;
jmp Win;
Fall:
stdout.put("Fall Semester", nl);
mov(BL,AL);
shr(7,AL);
and( %0000_0001, AL );
cmp(AL,1);
je SprFallPark;
add(51, EAX);
jmp ResCheck;
Spring:
stdout.put("Spring Semester", nl);
mov(BL,AL);
shr(7,AL);
and( %0000_0001, AL );
cmp(AL,1);
je SprFallPark;
stdout.put("No parking", nl);
add(51, EAX);
jmp ResCheck;
SprFallPark:
stdout.put("Parking", nl);
add(136, EAX);
jmp ResCheck;
Win:
cmp(AL, 11);
je Summer;
stdout.put("Winter Semester", nl);
mov(BL,AL);
shr(7,AL);
and( %0000_0001, AL );
cmp(AL,1);
je WinSumPark;
stdout.put("No Parking", nl);
add(51, EAX);
jmp ResCheck;
Summer:
stdout.put("Summer Semester", nl);
mov(BL,AL);
shr(7,AL);
and( %0000_0001, AL );
cmp(AL,1);
je WinSumPark;
stdout.put("No parking");
add(51, EAX);
jmp ResCheck;
WinSumPark:
stdout.put("Parking", nl);
add(133, EAX);
jmp ResCheck;
ResCheck:
mov(BL,AL);
shr(6,AL);
and( %0000_0001, AL );
cmp(AL,1);
je Res;
stdout.put("Non-Resident", nl);
mov(335,EDX);
jmp CalcUnits;
Res:
stdout.put("CA Resident", nl);
mov(46,EDX);
jmp CalcUnits;
CalcUnits:
ForLp:
mov(BL, AL);
and(%0000_1111, AL);
stdout.puti8(AL);
stdout.put(" units", nl);
ForLpTerminationTest:
cmp(AL, 0);
jle ForLpDone;
ForLpBody:
add(EDX, EAX);
ForLpDecrement:
dec(AL);
jmp ForLpTerminationTest;
ForLpDone:
stdout.put("Total Fees = $");
stdout.puti32(EAX);
end SMCFee;
这一定是一些逻辑问题,假设我输入了 cc。它打印出正确的字符串,但总量是错误的。如果我输入 4c,我会得到正确的字符串,但停车除外。它完全跳过了,总数也是错误的。谢谢你的帮助。
编辑:这是我输入 CC 时结果的图片。如您所见,它正确键入了类别,但没有得到相同的结果。我相信我的问题是我如何拥有声明标签。
【问题讨论】:
-
如果您向每个人展示一个简短的示例来展示您遇到的具体问题,您将获得更好的结果。这里不是人们为你做作业的地方。
-
您知道 EAX 实际上是 AL 和 AH 寄存器的组合吗?如果更改 AL 或 AH,它会更改 EAX 的值(AH=EAX 的高 8 位,AL 是 EAX 的低 8 位)。 AH 和 AL 是 EAX 的一部分。我问是因为我看到你将 total 移入 EAX,然后通过操纵 AH 和 AL 破坏 EAX。似乎你可能认为 AH 和 AL 完全独立于 EAX
-
@BenLindsay:我不同意。分配问题很长,但代码相当简单(而且相当短)。他显然已经尝试了分配,并告诉我们输入是什么,预期输出,并给了我们一个错误输出的例子(他的输出不应该是屏幕抓取,而只是将文本粘贴到问题中)。鉴于最终在这个网站上出现了很多家庭作业问题,这个肯定比其中许多问题要好。这绝对是不是一个给 Codez 的问题。
-
啊,是的,我完全忘记了重叠的寄存器。所以我想如果我把它移到一个不使用任何 16 或 8 位寄存器的不同的 32 位寄存器中,它不会覆盖数据?
-
@MichaelPetch 好的,很公平
标签: assembly hex bit-shift hla