传递参数 C ->NASM ->C [英] Passing Arguments C -> NASM -> C

查看:47
本文介绍了传递参数 C ->NASM ->C的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

诚然,这是一些家庭作业的帮助,但我似乎无法解决一个特定的问题.

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

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

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

我的期望:

请使用一串十六进制数字输入最多 4 位的十六进制整数:FBE您输入了:FBEFBE - F - 15

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

根据分配的校验位功能必须仅采用单个字符.因此,我将分解主要 NASM 函数中的字符串以获得完整功能.仍然试图让它一次使用一个角色..

C:

#include #include int main(void){字符输入[255];int dec_value;而 (1){printf ("请使用一串十六进制数字输入最大 4 位的十六进制整数:");scanf(%s",输入);如果(strlen(输入)<= 4){休息;}printf("字符串太长!\n");}printf("您输入的是:");printf ("%s\n",input);extern int hex2dec(char[]);dec_value = hex2dec(输入);printf ("%i",dec_value);如果(dec_value == -1){printf("有一个无效字符!\n");}别的 {printf ("字符 %s 的十进制值为:%d \n", input, dec_value);}返回0;}int 校验位(字符十六进制){printf (" - %c - ", 十六进制);if ( ((hex <= 70 && hex >= 65) || (hex >= 48 && hex <= 57) ) {如果(十六进制>= 65){printf("信");返回 ( (int) (hex-'A'+10 ));}别的 {printf("数字");返回十六进制 - 48;}}返回-1;}

NASM:

segment .data.text 段全球 hex2dec外部校验位,printf十六进制:推EBPmov EBP,ESP推EDX推EBXmov EDX,0D ;0 EDX异或 EBX,EBXmov EBX, DWORD [EBP+8] ;将字符串复制到 EDX推EBX调用 printf ;打印整个字符串呼叫校验位;传递字符来解释添加 ESP,4 ;返回时清空堆栈,;值在EAXpop EBX ;恢复EBXpop EDX ;恢复EDX流行电子血压计回复

解决方案

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

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

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

mov EDX, [EBX]

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

mov DL, [EBX]

你已经将 EDX 清零是一件好事(因为上面的指令只覆盖了底部 8 位).此时EDX包含了你要处理的字节,所以将EDX压入堆栈而不是EBX.

我希望这能扩展您对 x86 汇编的总体理解.

admittedly this is some homework help, but a specific problem I can't seem to get past.

I'm trying to write a program which takes a string in of hex characters, calls an assembler function which gives me the decimal value of the hex string. That assembler function calls a "checker" function in C which makes sure each character is a legal HEX value.

My question is, how do I take an EBX register in assembler and properly pass it to a C function expecting a character. I can't seem to properly pass from assembler back to C. Am I accidentally passing a pointer here? I also can't seem for the life of me to get an individual character out of EBX even by breaking it up into bytes.

Note, -1 is returned when the character is invalid.

What I'm hoping for:

Please enter a maximal 4 digit hex integer using a string of hex digits: FBE You entered: FBE FBE - F - 15

What I get: Please enter a maximal 4 digit hex integer using a string of hex digits: FBE You entered: FBE FBE - M - -1

EDIT: The check digit function according to the assignment must only take individual characters. So I will be breaking up the string in the main NASM function for the full functionality. Still trying to get it to work with once character at a time..

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

解决方案

Chris Dodd is correct-- send a char (8-bit byte) instead of a pointer (32-bit quantity).

So far, you don't seem to be doing anything with EDX except clearing it. Also, you don't need to clear EBX to 0 before loading its value from the stack (same as writing "a=12;a=65;"-- the first assignment is irrelevant because it is thrown away immediately).

Anyway, so you have loaded a pointer to the string into EBX. Now load the 8-bit byte that EBX points to. The syntax for this is [EBX], as such:

mov EDX, [EBX]

But doing that will load 4 bytes (because EDX is a 32-bit register). You only want the first byte, so specify a target register of the lower 8 bits of EDX (DL):

mov DL, [EBX]

It's a good thing you already cleared EDX to 0 (because the above instruction only overwrites the bottom 8 bits). At this point, EDX contains the byte you want to process, so push EDX on the stack instead of EBX.

I hope this has expanded your general understanding of x86 assembly.

这篇关于传递参数 C ->NASM ->C的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆