我正在努力学习Y86,所以我做了一个非常简单的程序。它有一个由三个长整数组成的数组,每个块都通过要求用户通过rdint
输入来填充。
编译好的(?)程序要求输入三个,但无法打印出来。
代码:
Main: irmovl Array, %edx
rdint %eax
rmmovl %eax, 0(%edx)
rdint %eax
rmmovl %eax, 4(%edx)
rdint %eax
rmmovl %eax, 8(%edx)
irmovl $10, %edi
Print: irmovl Array, %edx
mrmovl 0(%edx), %eax
wrch %eax
wrch %edi
mrmovl 4(%edx), %eax
wrch %eax
wrch %edi
mrmovl 8(%edx), %eax
wrch %eax
wrch %edi
halt
.align 4
Array:
.long 0
.long 0
.long 0
我的意见:
0
1
2
输出:
(three blank lines below)
Stopped in 22 steps at PC = 0x47. Exception 'HLT', CC Z=1 S=0 O=0
Changes to registers:
%edx: 0x00000000 0x0000004c
%edi: 0x00000000 0x0000000a
Changes to memory:
0x0004: 0x024008f2 0x00000001
0x0008: 0x00000000 0x00000002
Changes to memory: 0x0004: 0x024008f2 0x00000001 0x0008:
0x00000000 0x00000002
答案 0 :(得分:0)
该程序存在一个经典问题:ys文件中缺少新行,导致YAS行为不端。
第一个问题是由于YAS中的错误。如果查看YAS生成的yo文件,您将看到最后一个.long 0语句永远不会被定义。您可能还会看到yo文件中的第一行操作码是0x00,即nop(当YAS遇到没有相关换行符的最终指令时,它会将其包裹起来,搞砸了yo文件)
这意味着你松开了第一个irmovl数组,%edx(它变成某种废话,可能是0x00000000,即4个nops),所以你写第一个读取字符x'30'(ascii为'0')到edx指向的位置(可能是0x00000000,)是在第一条指令中(这是4次 - 记住你读了一个字符,但它最终是一个4字节的寄存器并保存为这样。)所以你正在写0x00000000和0x00000000的地址,这对YIS意味着寄存器没有改变,因此它没有显示在“内存更改”转储部分。
第二次读取时重复此操作,在第二个字中写入0x00000001(覆盖该位置的指令),第三次读取时,在第三个字中写入0x00000002(覆盖该位置的指令。)
现在,当然,你完全被冲了!您重置指向数组的指针(使用edx)并尝试打印内容,但Array(0),Array(4)和Array(8)包含0x00000000,因为这是您定义的(使用您的。由于Y86中未定义内存的默认设置为0x00000000,因此Array(0)和Array(4)的长4个语句自动为Array(8),因此,程序打印x'00'(因为你打印一个字符)从一个4字节的单词,),当然,这是垃圾。
您会注意到这符合YIS的转储。 eax没有显示,因为它的初始值为0x00000000。 edx和edi看起来很好,edi指向Array(8)。唯一更改的内存是程序的第二个和第三个字(分别用0x00000001和0x00000002覆盖)
总而言之。 YAS犯了一个错误。您必须通过在最后一个.long 0语句后添加换行来克服此问题。 YIS误导你,因为,批评!,当你用数据覆盖代码时,它不会抛出异常。