在第一个Y86计划中没有获得输出

时间:2011-11-07 02:38:15

标签: y86

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

1 个答案:

答案 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误导你,因为,批评!,当你用数据覆盖代码时,它不会抛出异常。