【问题标题】:Passing Arguments C -> NASM -> C传递参数 C -> NASM -> C
【发布时间】:2012-03-10 18:27:33
【问题描述】:

诚然,这是一些家庭作业帮助,但我似乎无法解决一个具体问题。

我正在尝试编写一个程序,它接受一个十六进制字符的字符串,调用一个汇编函数,它给我十六进制字符串的十进制值。该汇编器函数调用 C 中的“检查器”函数,以确保每个字符都是合法的 HEX 值。

我的问题是,如何在汇编程序中获取 EBX 寄存器并将其正确传递给需要字符的 C 函数。我似乎无法正确地从汇编程序传递回 C。我是否不小心在这里传递了一个指针?即使将单个字符分解为字节,我似乎也无法从 EBX 中取出单个字符。

注意,字符无效时返回-1。

我的期望:

请使用十六进制数字字符串输入最大 4 位十六进制整数:FBE 您输入了:FBE FBE - F - 15

我得到了什么: 请使用一串十六进制数字输入最大 4 位十六进制整数:FBE 您输入了:FBE FBE - M - -1

编辑:根据分配的校验位功能只能采用单个字符。因此,我将分解主 NASM 函数中的字符串以获得完整功能。仍在尝试让它一次使用一个角色..

C:

#include <stdio.h>
#include <string.h>

int main(void)
{  
    char  input[255];
int   dec_value;

while (1)
{
    printf ("Please enter a maximal 4 digit hex integer using a string of hex digits: ");
    scanf ("%s",input);
    if (strlen(input) <= 4)
    {
        break;
    }
    printf ("The string is too long!\n");
}

printf ("You entered: ");
printf ("%s\n",input);
extern int hex2dec(char[]);
dec_value = hex2dec(input);
printf ("%i",dec_value);
if (dec_value == -1) {
    printf ("There's an invalid character!\n");
}
else {
    printf ("Decimal value of character %s is:%d \n", input, dec_value); 
}       
return 0;
}

int checkdigit (char  hex)
{
    printf (" - %c - ", hex);
    if ( (hex <= 70 && hex >= 65) || (hex >= 48 && hex <= 57) ) {
        if ( hex >= 65 ) {
            printf ("Letter");
            return ( (int) (hex-'A'+10 ));
        }
        else {
            printf ("Number");
            return hex - 48;
        }
    }
    return -1;
}

NASM:

segment .data
segment .text
global  hex2dec
extern  checkdigit, printf

hex2dec:        
    push    EBP
    mov     EBP,ESP
    push    EDX
    push    EBX

    mov     EDX,0D         ; 0 EDX
    xor     EBX,EBX
    mov     EBX, DWORD [EBP+8]    ; copy the string to EDX

    push    EBX 

    call    printf      ; print whole string
    call    checkdigit     ; pass character to interpret

    add     ESP,4              ;on return clear the stack,                           
    ;the value is in EAX
    pop     EBX     ;restore EBX        
    pop     EDX     ;restore EDX
    pop     EBP 
    ret

【问题讨论】:

    标签: c assembly nasm


    【解决方案1】:

    您将参数传递给hex2dig(它是一个char *)到checkdigit(它需要一个char)。您需要将一个字符实际加载到一个寄存器中,然后将该寄存器压入堆栈以将一个字符传递给checkdigit

    【讨论】:

    • 嗯,是的。这是我什至无法做到的,将 4 字节字符串分解为单个字符。我试过: mov EDX,EBX / and EDX,00000000000000000000000011111111B / 按下 EDX 来尝试屏蔽一个字符。它使用 and 指令在汇编代码中产生段错误。也尝试过轮班。
    【解决方案2】:

    Chris Dodd 是正确的——发送一个 char(8 位字节)而不是一个指针(32 位数量)。

    到目前为止,除了清除它之外,您似乎没有对 EDX 做任何事情。此外,在从堆栈中加载其值之前,您不需要将 EBX 清除为 0(与编写“a=12;a=65;”相同——第一个赋值无关紧要,因为它会立即被丢弃)。

    无论如何,您已经将一个指向字符串的指针加载到 EBX 中。现在加载 EBX 指向的 8 位字节。其语法为 [EBX],如下所示:

    mov EDX, [EBX]
    

    但是这样做会加载 4 个字节(因为 EDX 是一个 32 位寄存器)。你只想要第一个字节,所以指定一个EDX(DL)低8位的目标寄存器:

    mov DL, [EBX]
    

    很高兴您已经将 EDX 清为 0(因为上述指令只覆盖了底部的 8 位)。此时,EDX 包含您要处理的字节,因此将 EDX 压入堆栈而不是 EBX。

    我希望这能扩展您对 x86 汇编的一般理解。

    【讨论】:

    • 谢谢!为一些代码混乱道歉。我真的不确定我传递的是指针还是值(就像我想要的那样)。这说明了很多。是的,当我编程太久时,它有助于揭开一些东西的神秘面纱。
    • 通常你希望movzx edx, byte [ebx] 加载一个字节,而不是清零 EDX 然后合并一个新的低字节。
    猜你喜欢
    • 2014-06-26
    • 2016-09-03
    • 2013-02-25
    • 1970-01-01
    • 1970-01-01
    • 2010-12-12
    • 2019-04-18
    • 1970-01-01
    相关资源
    最近更新 更多