1

我正在努力学习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
4

1 回答 1

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 个 nops - 请记住,您读取了一个字符,但它最终在一个 4 字节寄存器中并按原样保存。)所以你正在写0x00000000 到和地址是 0x00000000,这对 YIS 意味着寄存器没有更改,因此它没有显示在“更改内存”转储部分中。

您重复此操作,第二次读取,在第二个字中写入 0x00000001(覆盖该位置的指令),第三次读取,在第三个字中写入 0x00000002(覆盖该位置的指令。)

现在,当然,你完全被冲洗了!您重置指向数组的指针(使用 edx,)并尝试打印内容,但 Array(0)、Array(4) 和 Array(8) 包含 0x00000000,因为这是您定义的(使用您的 . Array(0) 和 Array(4) 的长 4 条语句和 Array(8) 的自动语句,因为 Y86 中未定义内存的默认设置是 0x00000000。因此,程序打印 x'00'(因为您打印一个字符来自一个 4 字节的字,)当然是垃圾。

您会注意到这与 YIS 的转储相符。eax 没有显示,因为它与初始值 0x00000000 没有变化。edx 和 edi 看起来 A-OK,edi 指向 Array(8)。唯一改变的内存是程序的第二个和第三个字(分别被 0x00000001 和 0x00000002 覆盖)

所以,总结一下。YAS 犯了一个错误。您必须通过在最后一个 .long 0 语句之后添加一个新行来克服这个问题。YIS 会误导您,因为关键!当您用数据覆盖代码时,它不会引发异常。

于 2012-11-08T04:00:30.177 回答