将输入的字与 x86 GNU GAS 程序集中的数组进行比较

Comparing Inputted Word to Array in x86 GNU GAS Assembly

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

本质上,我试图输入一串字母(没有数字或符号),然后将每个输入的字母与代表北约军事音标的 .asciz 值数组进行比较(Alpha, Bravo, Charlie, etc.) 并输出对应于该字母的代表军事等价物。

这就是我卡住的地方。我是 Assembly 的新手,这是一项家庭作业,因此非常需要和感谢帮助。我的教授不擅长提供学习这些东西的资源,而且很难在网上找到解决确切问题的好资源。

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

下面是我正在尝试执行的操作的 C# 表示。

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();
    }
}

编辑:

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

.section .data

MAlpha:
.asciz  "Alpha    \n"
.equ    ElementLen, .-MAlpha
.asciz  "Bravo    \n"
.asciz  "Charlie  \n"
.asciz  "Delta    \n"
.asciz  "Echo     \n"
.asciz  "Foxtrot  \n"
.asciz  "Golf     \n"
.asciz  "Hotel    \n"
.asciz  "India    \n"
.asciz  "Juliet   \n"
.asciz  "Kilo     \n"
.asciz  "Lima     \n"
.asciz  "Mike     \n"
.asciz  "November \n"
.asciz  "Oscar    \n"
.asciz  "Papa     \n"
.asciz  "Quebec   \n"
.asciz  "Romeo    \n"
.asciz  "Sierra   \n"
.asciz  "Tango    \n"
.asciz  "Uniform  \n"
.asciz  "Victor   \n"
.asciz  "Whiskey  \n"
.asciz  "X-Ray    \n"
.asciz  "Yankee   \n"
.asciz  "Zulu     \n"
.asciz  "         \n"
.equ    MAlphaLen, .-MAlpha

Input:
.fill   80
.equ    InputLen, .-Input

InputMSG:
.ascii  "Please enter a word: "
.equ    InputMSGLen, .-InputMSG

BlankLine:
.ascii  "\n"
.equ    BlankLineLen, .-BlankLine

Converting:
.ascii  "\nConverting to NATO Alphabet...\n\n"
.equ    ConvertingLen, .-Converting

.section .bss
.section .text
.globl   _start

GetInput:
    movl    , %eax
    movl    , %ebx
    movl    $InputMSG, %ecx
    movl    $InputMSGLen, %edx
    int     [=11=]x80

    movl    , %eax
    movl    [=11=], %ebx
    movl    $Input, %ecx
    movl    $InputLen, %edx
    int     [=11=]x80
    ret

PrintInput:
    movl    , %eax
    movl    , %ebx
    movl    $BlankLine, %ecx
    movl    $BlankLineLen, %edx
    int     [=11=]x80

    movl    , %eax
    movl    , %ebx
    movl    $Input, %ecx
    movl    $InputLen, %edx
    int     [=11=]x80

    movl    , %eax
    movl    , %ebx
    movl    $Converting, %ecx
    movl    $ConvertingLen, %edx
    int     [=11=]x80
    ret

Convert:
    # Get first letter of input string
    # Compare letter to first letter of each array entry
    # When match is found, print Array entry to screen
    # Repeat until end of input string

    movl    $Input, %eax
    movl    $MAlpha, %edi
    call    Loop
    ret

Loop:
    movb    (%eax), %al
    cmp     [=11=]x0A, %al
    je      Finished

    call    CompareAlpha

    jmp     Loop

CompareAlpha:
    movb    (%edi), %bl
    cmpb    %bl, %al
    je      PrintWord
    addl    $ElementLen, %edi
    jmp     CompareAlpha

PrintWord:
    movl    , %eax
    movl    , %ebx
    movl    (%edi), %eax
    movl    $ElementLen, %edx
    int     [=11=]x80

Finished:
    call    ExitProg

_start:
    call    GetInput
    call    PrintInput
    call    Convert
    call    ExitProg

PrintMAlpha:
    movl    , %eax
    movl    , %ebx
    movl    $MAlpha, %ecx
    movl    $MAlphaLen, %edx
    int     [=11=]x80

ExitProg:
    movl    , %eax
    movl    [=11=], %ebx
    int     [=11=]x80

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

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

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

  3. CompareAlpha 不会在连续调用时重置 %edi。因此,如果第一个字符是 'H'%edi 将在调用后指向 "Hotel"。如果下一个字符是 ECompareAlpha 将从 "Hotel" 开始向前搜索它。它当然不会找到它,所以它会跑到数组的末尾并崩溃。

  4. PrintWord 将字符串的四个字节加载到 %eax(覆盖系统调用号),而它应该将字符串的地址加载到 %ecx.将 movl (%edi), %eax 替换为 movl %edi, %ecx(注意它现在是 register-to-register 移动而不是从内存加载)。

  5. PrintWord 破坏了寄存器 %eax, %ebx, %ecx, %edx,其中一些它的调用者期望保持不变。压入和弹出这些寄存器,或者重写 CompareAlpha 在调用它之前这样做。

  6. PrintWord 末尾缺少一个 ret,因此它落入 ExitProg.

修复这些后,我能够成功转换字符串 "HELLO"

这些都可以通过 single-stepping gdb 调试器(si 命令)中的代码找到,并观察寄存器 (display $eax) 的内容及其指向的内容到(display/s $edi,等等)。我建议练习这个。

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

此外,作为一般提示,明智的做法是记录您的每个子例程:它究竟做了什么,它期望在哪些寄存器中输入并保留其输出,以及它破坏了哪些寄存器?您可能想尝试在它们之间建立一些共性,甚至可能创建您自己的标准调用约定。