0

嗨,我正在处理一个装配,技术上是 HLA(高级装配)任务,我是一个需要帮助的错误。这是作业:
编写一个 HLA 汇编语言程序,该程序实现一个函数,该函数正确识别所有参数是否不同,根据是否满足此条件,在 EAX 中返回 0 或 1。此函数应具有以下签名:

程序allDifferent(x:int16;y:int16;z:int16);@无显示;@无框;

下面显示的是一个示例程序对话。

喂我 X:205
喂我 Y:170
喂我 Z:91
allDifferent 返回真!

Feed Me X: 0
Feed Me Y: 0
Feed Me Z: 0
allDifferent 返回 false!

喂我 X:121
喂我 Y:121
喂我 Z:121
allDifferent 返回 false!

这是我的代码。我的问题是,无论我输入什么数字,它总是返回“allDifferent 返回 false!” 谢谢你的帮助。

program allDifferent;
#include( "stdlib.hhf" );
static
iDataValue1 : int16 := 0;
iDataValue2 : int16 := 0;
iDataValue3 : int16 := 0;
iDataValue4 : int16 := 0;


procedure allDiff( x: int16; y : int16; z : int16 ); @nodisplay; @noframe;
static
returnAddress : dword;
temp : int16;

begin allDiff;
pop(returnAddress);
pop(z);
pop(y);
pop(x);
pop(temp);

push(returnAddress);
push(AX);
push(BX);

mov(x, AX);
cmp(y, AX);
je xyequal;
jmp notequal;

xyequal:
mov(y, BX);
cmp(z, BX);
je equal;
jmp notequal;

equal:
mov(0, EAX);
jmp ExitSequence;

notequal:
mov(1, EAX);
jmp ExitSequence;


ExitSequence:
pop(BX);
pop(AX);
ret();
end allDiff;

begin allDifferent;
stdout.put( "Gimme a X:" );
stdin.get( iDataValue1 );
stdout.put("Gimme a Y:");
stdin.get(iDataValue2);
stdout.put("Gimme a Z:");
stdin.get(iDataValue3);

push( iDataValue1 );
push( iDataValue2 );
push( iDataValue3 );
push( iDataValue4 );
call allDiff;

cmp(EAX, 1);
je ISDIFFERENT;
jmp NOTDIFFERENT;


ISDIFFERENT:
    stdout.put("allDifferent retursn true",nl);
    jmp EndProgram;

NOTDIFFERENT:
    stdout.put("allDifferent retursn false",nl);
    jmp EndProgram;

stdout.newln();

EndProgram:


end allDifferent;
4

1 回答 1

1
notequal:
mov(1, EAX);         <<- good.
jmp ExitSequence;
:
ExitSequence:
pop(BX);
pop(AX);             <<- not so good.
ret();

仔细看看AX上述序列中发生了什么。即使您将其设置为代码中的某个值,您也会用指令覆盖该值pop,恢复AX到您输入函数时的任何值。

汇编器函数通常应该保留和恢复调用者可能正在使用的寄存器,但当您想使用该寄存器返回一些有用的信息时则不需要。


此外,您的参数未得到正确处理。你按顺序推送它们{p1, p2, p3, junk}(不知道为什么你有第四个参数,因为你不使用它做任何事情)。

但是,在函数中,您按顺序弹出{x, y, z, temp}。现在,因为堆栈是 LIFO(后进先出)结构,所以映射将是:

junk -> x
p3   -> y
p2   -> z
p1   -> temp

这意味着该x变量将被设置为某个任意值,而不是您传入的“真实”参数之一。

如果您不打算使用第四个参数,我建议您去掉它。如果您确实想在某个时候使用它,则需要关联您的推送和弹出操作,以便获得正确的值。


顺便说一句,您可能还可以通过几种方式使您的代码更干净。

首先,没有真正需要使用(或保存/恢复)BX,因为AX在本地使用(在一个小块中mov/cmp)。您可以AX同时使用xy支票和yz支票。

其次,你可以去掉很多实际上不需要的跳跃。你的算法的伪代码可以归结为一个非常简单的:

    if x and y are same, go to NOTDIFF.
    if y and z are same, go to NOTDIFF.
DIFF:
    set AX to 1
    go to END
NOTDIFF:
    set AX to 0
END:
    return
于 2015-11-13T02:30:09.947 回答