Author Topic: Help with Passing Arguments C -> NASM -> C  (Read 19167 times)

Offline nasmnoob

  • Jr. Member
  • *
  • Posts: 2
Help with Passing Arguments C -> NASM -> C
« on: March 10, 2012, 04:59:31 PM »
Hey all, admittedly this is some homework help.

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:

Code: [Select]
#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;
}

Code: [Select]
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, [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


Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: Help with Passing Arguments C -> NASM -> C
« Reply #1 on: March 10, 2012, 07:47:07 PM »
If you were to change your checkdigit function to accommodate the fact that you did pass a reference to a C string, without assuming that it has a fixed/predetermined size, how would you do so?

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Help with Passing Arguments C -> NASM -> C
« Reply #2 on: March 10, 2012, 08:51:32 PM »
Besides the issue Keith mentions, one obvious error jumps out at me:

Code: [Select]
                mov     EBX, [EBP+8]    ; copy the string to EDX

push EBX

call printf ; print whole string

Printf expects the address of a format string as its "first" (last pushed) parameter. Using the string that you passed into this function for that purpose isn't likely to produce useful results. Providing an appropriate format string here may give you a better idea what's going on in your function.

I'll try to look at this further, later.

Best,
Frank



Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: Help with Passing Arguments C -> NASM -> C
« Reply #3 on: March 10, 2012, 09:06:44 PM »
Printf expects the address of a format string as its "first" (last pushed) parameter.

This will only cause an issue if you happen to have a format (%) code, as that equates to printf looking for more data on the stack in this case. So it is a potential source of "random" bugs.

However, Frank's illustration does suggest that, for safety/stability reasons, when using printf to print potentially random/variable string data, you should use "%s" and then supply the desired string to print.

A more direct way to address this issue is to use puts instead of printf.

Offline Keith Kanios

  • Full Member
  • **
  • Posts: 383
  • Country: us
    • Personal Homepage
Re: Help with Passing Arguments C -> NASM -> C
« Reply #4 on: March 10, 2012, 09:09:19 PM »
A more direct way to address this issue is to use puts instead of printf.

Also note that puts will automatically append a newline, so you will not need to use "\n" within the string.

Offline nasmnoob

  • Jr. Member
  • *
  • Posts: 2
Re: Help with Passing Arguments C -> NASM -> C
« Reply #5 on: March 11, 2012, 09:34:42 PM »
If you were to change your checkdigit function to accommodate the fact that you did pass a reference to a C string, without assuming that it has a fixed/predetermined size, how would you do so?

Unfortunately I cannot do that, the checkdigit function must according to the assignment only check individual characters.

Printf expects the address of a format string as its "first" (last pushed) parameter.

This will only cause an issue if you happen to have a format (%) code, as that equates to printf looking for more data on the stack in this case. So it is a potential source of "random" bugs.

However, Frank's illustration does suggest that, for safety/stability reasons, when using printf to print potentially random/variable string data, you should use "%s" and then supply the desired string to print.

A more direct way to address this issue is to use puts instead of printf.

I will definitely try puts and see if I can get a little further.

Thanks guys! I didn't realize no emails would show up in my inbox mentioning replies..

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Help with Passing Arguments C -> NASM -> C
« Reply #6 on: March 11, 2012, 10:50:19 PM »
Click the "notify" option, and you "should" get email notification of any replies posted. (but it's an imperfect world!)

If your "checkdigit" function is expected to check only one character at a time, then that's what you've got to pass to it - you're just passing the address of the string back. When "checkdigit" returns, it has done the character-to-number conversion for you, and eax contains the number. Multiply a "result so far" (starting at zero) by 16 and add in the number you've got. Put the "result so far" in eax to return the decimal value.

I've got it "kinda working", but the display is a mess. Needs more work. Note that your "checkdigit" accepts only uppercase 'A' - 'F'... Is that okay, or do you need to "fix" it?

Best,
Frank