在x86 GNU GAS程序集中比较输入的单词与数组

问题描述

这实际上是我今天针对这个特定问题的第二个问题,但是另一个问题很快得到了回答。

从本质上讲,我试图输入一串字母(没有数字或符号),然后将每个输入的字母与代表北约军事语音字母(Alpha,Bravo,查理(Charlie)等人),并输出与该信件等效的代表军事。

这就是我被困住的地方。我对Assembly来说还很陌生,这是一项家庭作业,因此非常需要帮助。我的教授不太擅长提供学习这些知识的资源,而且很难找到在线解决具体问题的良好资源。

任何帮助将不胜感激。特别是关于如何比较输入到数组的每个字母。我已经成功地将输入存储在变量中。

下面是我正在尝试做的C#表示。

.asciz

编辑:

因此,我相信这应该可以完成我想做的事情,但是它似乎没有按预期的方式工作。它在调试器中比较正确的东西,但是当它要打印数组的各个部分时,它根本不打印任何内容

class MilAlpha
{
    static void Main(string[] args)
    {
        string input;
        string[] miliAlpha = { "Alpha","Beta","Charlie","Delta","Echo","Foxtrot","Golf","Hotel","India","Juliet","Kilo","Lima","Mike","November","Oscar","Papa","Quebec","Romeo","Sierra","Tango","Uniform","Victor","Whiskey","X-Ray","Yankee","Zulu" };

        Console.WriteLine("Enter a string of text: ");
        input = Console.ReadLine();

        for (int i = 0; i < input.Length; i++) {
            for (int j = 0; j < miliAlpha.Length; j++) {

                if (input[i] == ' ')
                    Console.WriteLine("\n")
                
                string temp = miliAlpha[j].ToLower();

                if (input[i] == temp[0])
                    Console.WriteLine("\n" + miliAlpha[j] + "\n");

            }
        }

        Console.ReadKey();
    }
}

解决方法

有一些错误可以帮助您入门:

  1. Loop中,您将指针保持在%eax中的输入字符串,但是将字符加载到%al中,这是{{1}的低字节},从而破坏其价值。为其中之一选择另一个寄存器。

  2. 您永远不会在%eax中增加指针,因此它将永远循环(如果由于您的其他错误之一而导致指针没有首先崩溃)。

  3. Loop不会在连续调用中重置CompareAlpha。因此,如果第一个字符是%edi,则通话后'H'将指向%edi。如果下一个字符是"Hotel",则E将从CompareAlpha开始向前搜索。当然,它不会找到它,因此它会在数组末尾运行并崩溃。

  4. "Hotel"将字符串的四个字节加载到PrintWord中(覆盖系统调用号),而应该将字符串的地址加载到%eax中。将%ecx替换为movl (%edi),%eax(请注意,这是一次寄存器到寄存器的移动,而不是从内存中加载)。

  5. movl %edi,%ecx Clobbers寄存器PrintWord,其调用者希望其中的一些保持不变。按下并弹出这些寄存器,或者在调用之前重写%eax,%ebx,%ecx,%edx来完成此操作。

  6. CompareAlpha最后缺少一个PrintWord,因此掉入了ret

修复这些问题后,我能够成功转换字符串ExitProg

所有这些都可以通过单步执行"HELLO"调试器(gdb命令)中的代码并观察寄存器(si)的内容及其指向的内容({{ 1}}等)。我建议练习这个。

请注意,一种更有效的设计,而不是通过代码字数组进行线性搜索,将是简单地对其进行索引。取出您的字符并减去display $eax(0x41)的ASCII码,乘以display/s $edi,然后加到'A'。现在,您有了一个无需循环的指向所需代码字的指针。如果像your other post中那样使用辅助指针数组,这将更加容易,因为每个指针的长度为4,因此您可以使用SIB寻址模式并执行$ElementLen;确保$MAlpha的高24位为零。这也避免了用空格填充所有代码字的麻烦(尽管那样,您将需要编写自己的movl MAlpha(,%eax,4),%edi来计算长度,或者具有单独的长度数组,或者一次写出一个字节)直到最后看到0。

此外,作为一个一般性提示,记录每个子例程也是明智的:它到底做了什么,期望在哪个寄存器中输入并保留其输出,而哪个寄存器中有内容呢?您可能想尝试在两者之间具有一些共同点,甚至可能创建自己的标准调用约定。