X86 Assembly Calling Another Function

Click For Summary

Discussion Overview

The discussion revolves around the implementation of a recursive factorial function in x86 assembly language. Participants explore the mechanics of function calls, register usage, and multiplication operations within the context of assembly programming.

Discussion Character

  • Technical explanation
  • Exploratory
  • Debate/contested

Main Points Raised

  • Some participants question why the factorial function pushes the ebx register again after it has already been pushed in the first function.
  • There is a discussion about the behavior of the mul instruction, specifically that it multiplies the value in eax with a source operand and stores the result in edx:eax.
  • Some participants note that the factorial function is missing a recursive call and suggest that the input parameter should be decremented before each call.
  • One participant raises a concern about handling cases where the input exceeds 13, questioning how to combine the results in edx and eax.
  • There is clarification that imul is used for signed integers while mul is for unsigned integers, with a suggestion to use unsigned integers in this context.

Areas of Agreement / Disagreement

Participants express uncertainty about the complete implementation of the factorial function and the necessity of certain instructions. Multiple competing views exist regarding the handling of larger integers and the use of registers, indicating that the discussion remains unresolved.

Contextual Notes

Participants acknowledge missing code segments and assumptions about prior knowledge of recursive functions in C. There are references to specific behaviors of assembly instructions that may depend on the context of the implementation.

whitehorsey
Messages
188
Reaction score
0
1.
firstFunction (parameters has an input and an output){
(ebx holds the input, ecx holds the output)
...
mov eax, 1

push ebx
call factorial
pop ebx

...
}

factorial(unsigned int n){
push ebx
mul ebx
}

3. I understand that you push ebx in the first function because you want to pass the input number to the factorial function. However, why does factorial function need to push ebx again? In addition, the line mul ebx (multiplies with eax) how does it know to multiply with eax. I thought I had to do something like mul ebx, eax yet that causes the build to fail.
 
Physics news on Phys.org
Seems like there's missing code from this. It appears the goal is a recursive version of factorial, but the factorial function is not calling itself. The destination for mul is always edx:eax, so the destination operand is not specified. The operation is edx:eax = eax x (source operand), where edx receives the upper 32 bits of the product, and eax receives the lower 32 bits of the product. There are other instructions where the register used is fixed, such as div, or the scan instructions such as scasb.
 
Last edited:
rcgldr said:
Seems like there's missing code from this. It appears the goal is a recursive version of factorial, but the factorial function is not calling itself. The destination for mul is always edx:eax, so the destination operand is not specified. The operation is edx:eax = eax x (source operand), where edx receives the upper 32 bits of the product, and eax receives the lower 32 bits of the product. There are other instructions where the register used is fixed, such as div, or the scan instructions such as scasb.

Ooh so, edx has 0000 0000 0000 0000 while eax has whatever n is?

Sorry about the missing code! After the multiply stuff it calls the function again but before it calls the function it pushes ebx again. Why does it do that?
 
whitehorsey said:
Ooh so, edx has 0000 0000 0000 0000 while eax has whatever n is?
eax would should have the multiplicand or multiplier before, and the product after. until you try to calculate 13!, which is greater than 2^32. In this case the two numbers to be multiplied are 13 x 12! = hex 17328CC00, so in this case edx = hex 1 and eax = hex 7328CC00

whitehorsey said:
Sorry about the missing code! After the multiply stuff it calls the function again but before it calls the function it pushes ebx again. Why does it do that?
Because the input parameter to factorial needs to be pushed onto the stack before each call. The code is also missing the part where the parameter is decremented (subtract 1) before a call is made, and a check as the start of the factorial function to see if the input parameter is 0.

I'm going to assume that you were supposed to have already been given an example of how to do recursive factorial in C, and the point of this exercise is to implement the same function in assembly. Here is an example written in C:

Code:
unsigned int factorial(unsigned int n)
{
    if(n == 0)
        return(1);
    else
        return n * factorial(n-1);
}

int main()
{
unsigned int result;

    result = factorial(12);

/* ... */
    return(0);
}
 
Last edited:
rcgldr said:
eax would should have the multiplicand or multiplier before, and the product after. until you try to calculate 13!, which is greater than 2^32. In this case the two numbers to be multiplied are 13 x 12! = hex 17328CC00, so in this case edx = hex 1 and eax = hex 7328CC00

Oh sooo would I also need to have a mov edx, 1 in case I'm tested with integers >= 13? If so, how would I combine eax and edx together to get it's output?

rcgldr said:
Because the input parameter to factorial needs to be pushed onto the stack before each call. The code is also missing the part where the parameter is decremented (subtract 1) before a call is made, and a check as the start of the factorial function to see if the input parameter is 0.

I'm going to assume that you were supposed to have already been given an example of how to do recursive factorial in C, and the point of this exercise is to implement the same function in assembly. Here is an example written in C:

Code:
unsigned int factorial(unsigned int n)
{
    if(n == 0)
        return(1);
    else
        return n * factorial(n-1);
}

int main()
{
unsigned int result;

    result = factorial(12);

/* ... */
    return(0);
}

Ah I get it now! I'm so sorry again for not stating that I have also tested cases where the input parameter is 0 and I also did the subtraction.

I was wondering what is the difference between imul and mul?
 
whitehorsey said:
Oh sooo would I also need to have a mov edx, 1 in case I'm tested with integers >= 13? If so, how would I combine eax and edx together to get it's output?
Since you're doing 32 bit code, I wouldn't worry about the >= 13 cases, so you can ignore edx for now. If you were doing 64 bit code, you would be using rax, rbx, ... , instead of eax, ebx, ... . I would assume this is not part of your class assignment.

whitehorsey said:
sorry again for not stating that I have also tested cases where the input parameter is 0 and I also did the subtraction.
It would help to show all of the code for your factorial function. It's not going to be that large.

whitehorsey said:
I was wondering what is the difference between imul and mul?
imul is for signed integers, mul is for unsigned integers. Might as well use unsigned integers in this case.
 
rcgldr said:
Since you're doing 32 bit code, I wouldn't worry about the >= 13 cases, so you can ignore edx for now. If you were doing 64 bit code, you would be using rax, rbx, ... , instead of eax, ebx, ... . I would assume this is not part of your class assignment.

Ooooh I see!

rcgldr said:
It would help to show all of the code for your factorial function. It's not going to be that large.

imul is for signed integers, mul is for unsigned integers. Might as well use unsigned integers in this case.

Okay! Thank You! :smile:
 

Similar threads

  • · Replies 13 ·
Replies
13
Views
16K
  • · Replies 3 ·
Replies
3
Views
2K
Replies
19
Views
6K
  • · Replies 7 ·
Replies
7
Views
7K
  • · Replies 19 ·
Replies
19
Views
6K
  • · Replies 6 ·
Replies
6
Views
6K
  • · Replies 4 ·
Replies
4
Views
6K
  • · Replies 1 ·
Replies
1
Views
2K
  • · Replies 4 ·
Replies
4
Views
5K
  • · Replies 7 ·
Replies
7
Views
3K