Reputation: 53
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
Upvotes: 3
Views: 5409
Reputation: 13216
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.
Upvotes: 1
Reputation: 126140
You're passing the argument to hex2dig
(which is a char *) to checkdigit
(which expects a char). You need to actually load a character into a register and then push that register onto the stack to pass a char to checkdigit
Upvotes: 3