Assembly language multiplication problems
So i have a problem running a homework assignment for assembly code. The code is supposed to just do simple multiplication but it can't use the imul function or anything simple like that, it has to use shifts.
There must be something wrong with the assembly code because when I have emacs compile and run main.c and multiply.s, without having main.c actually call the multiply function, it outputs just fine. On the other hand, when I have it call the multiply function, it forces it not to have output
INPUT I HAVE:
I'm expecting my c file, with the following code, to call multiply on x and y, which are defined as 34 and 47 respectively.
#include <stdio.h>
extern int multiply();
extern int x, y;
int main()
{
x = 34;
y = 47;
printf("%d * %d = %d\n", x, y, multiply());
}
OUTPUT I EXPECT: I expect it to run multiply, which should correctly calculate the product of the two, and then print out the following
34 * 47 = 1598
OUTPUT I GET:
None. I get a message when I run it from the shell command saying
Shell command executed with no output
MY PROBLEM:
I keep getting an error when I run gcc -m32 main.c multiply.s
that says
gcc -m32 multiply.s main.c
ld: warning: PIE dis开发者_如何学Goabled. Absolute addressing (perhaps -mdynamic-no-pic) not allowed in code signed PIE, but used in _multiply from /var/folders/ct/6_dmqq_11s9951v72wbcx06m0000gn/T//cc9DcDxr.o. To fix this warning, don't compile with -mdynamic-no-pic or link with -Wl,-no_pie
It generates an a.out file, and when I run the a.out file from the shell it gives me this
(Shell Command succeeded with no output)
Ideas?
Here's my code:
.globl _multiply
_multiply:
.data
.globl _x
.globl _y
_prod: .long 0
_x: .long 0
_y: .long 0
pushl %ebp
movl %ebp,%esp
movl _x,%eax
movl _y,%edx
movl $1,%ecx
LOOP:
cmpl $0,%eax
je DONE
and %eax,%ecx
cmp $0,%ecx
je CONTINUE
add %edx,_prod
CONTINUE:
shrl $1,%eax
shll $1,%edx
jmp LOOP
DONE:
movl _prod,%eax
popl %ebp
ret
The error you're getting seems to be related to using an absolute address.
One way to avoid that would be to receive your inputs on the stack (you're setting up for that anyway), and return the result in eax. You should be able to multiply two numbers using around 4 registers, with no other storage at all.
Also note that right now it looks like its stack usage is mismatched. You have a prolog that pushes ebp, but I don't see anything to pop it back off before the return.
First off, great job on improving your question +1 for that.
A few things I can see:
_multiply:
.data
.globl _x
.globl _y
_prod: .long 0
_x: .long 0
_y: .long 0
pushl %ebp
Here you're defining data in your function. That is instead of having instructions at the start of your function you have a bunch of data (which, when interpreted as instructions will not behave nicely). Move the data away, something like (notice that you want to switch back to the text segment for the code):
.data
_x: .long 0
_y: .long 0
.text
_multiply:
pushl %ebp
Also:
movl %ebp,%esp
Is almost certainly not what you want, as you're moving overwriting the stack pointer with contents of %ebp
. Change that to:
movl %esp,%ebp
(AT&T syntax can be confusing, you could consider using .intel_syntax prefix
but that means changing all of the code).
Your multiplication function also won't work (you're overwriting values you're counting on later), but first things first :)
PS: You should also put return 0;
at the end of your main
function.
精彩评论