传递参数 C ->NASM ->C [英] Passing Arguments 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屋!