Hey, i am learning from Programming from the ground up. I am having a bit of trouble with the pushl and popl commands. I'm a newbie with ASM and really just starting out on it, i am on a x86-64 im presuming it will run the x86 32bit code. I ran other example code which didn't use push or pop, and it ran fine; it only really moved values around in the registers.

The error im getting on ALL my push and pop commands:

Error: suffix or operands invalid for `push'
Error: suffix or operands invalid for `pop'

Here is the source code which im using, i've tested it on other people's snippets as well but with the same result. So i don't think its the source code.

#PURPOSE:  Program to illustrate how functions work
#          This program will compute the value of
#          2^3 + 5^2
#
#Everything in the main program is stored in registers,
#so the data section doesn’t have anything.

 .section .data

 .section .text
 
 .globl _start
_start:
	pushl $3
	pushl $2
	call power
	addl $8,%esp
	
	pushl %eax
	
	pushl $2
	pushl $5
	
	call power
	addl $8,%esp
	popl %ebx
	
	addl %eax, %ebx
	movl $1, %eax
	int $0x80
	
#PURPOSE: This function is used to compute
#           the value of a number raised to
#           a power.
#
#INPUT:     First argument - the base number
#           Second argument - the power to
#                             raise it to
#
#OUTPUT:    Will give the result as a return value
#
#NOTES:     The power must be 1 or greater
#
#VARIABLES:
#           %ebx - holds the base number
#           %ecx - holds the power
#
#           -4(%ebp) - holds the current result
#
#           %eax is used for temporary storage
#

 .type power, @function
power:
	pushl %ebp
	movl %esp,ebp
	subl $4,%esp
	
	movl 8(%ebp), %ebx 
	movl 12(%ebp),%ecx 
	movl %ebx, -4(%ebp)
	
power_loop_start:
	cmpl $1,ecx
	je end_power
	movl -4(%ebp),%eax
	imull %ebx,%eax
	
	movl %eax,-4(%ebp)
	
	decl %ecx
	jmp power_loop_start
	
end_power:
	movl -4(%ebp),%eax
	movl %ebp,%esp
	popl %ebp
	ret

I'm not an expert at ASM myself but I know that this code is way bigger than it needs to be.

What assembler do you use?
Why are you using %???????

With the push and pop instructions, you add a value into the stack (like eax). I think you need to use registers to do what your doing.


I think this will do the job, but I haven't tested it as I don't know what assembler your using...

#PURPOSE:  Program to illustrate how functions work
#          This program will compute the value of
#          2^3 + 5^2
#
#Everything in the main program is stored in registers,
#so the data section doesn’t have anything.

 .section .data

 .section .text
 
 .globl _start
_start:
	mov eax, 2
	mov ebx, 3
	call power
	
	mov edx, ecx
	
	mov eax, 5
	mov ebx, 2
	call power
	
	add ecx, edx
	int 0x80
	
#PURPOSE: This function is used to compute
#           the value of a number raised to
#           a power.
#
#INPUT:     First argument - the base number
#           Second argument - the power to raise it to
#
#OUTPUT:    Will give the result in ecx
#
#NOTES:     The power must be 1 or greater
#
#VARIABLES:
#           eax - holds the base number
#           ebx - holds the power
#
#
#           edx is used for temp storage
#

 .type power, @function
power:
	push edx
	jmp .power_loop

.power_loop:
	cmp edx, 1
	je .power_end
	imul edx, eax, ebx
	sub ebx, 1
	jmp .power_loop
	
.power_end:
	mov ecx, edx
	pop edx
	ret

Its the GNU Assembler AKA GAS, it uses the AT&T syntax reason for the % and $. And the source code is copied from an example in "programming from the ground up". I've used other peoples source which uses push and pop and it didn't work either with the same errors.

OH - That makes sense now :)

Hi

pushl is a 32 bit instruction (suffix l = long = 32bit). So the assembly is wrong for 64bit machines, except you do special compiling and linking with gcc and ld. You need to tell the compiler and the linker that you would like to get 32bit-code. For the compiler there is the -m32 option. Then you should do separate linking with ld. Here you must specify only 32 bit libraries! Then the result should run on 64bit systems too.

I personally would hardly start to learn assembly programming with that exotic syntax of gasm, Just consider the prefixes $ and % for variables, constants and registers. Also the order of operands is quite opposite to the rest of the world which follows IBM convention, for example MASM, MASM32, TASM, NASM, Intel ASM, WASM admit MOV DESTINATION, SOURCE, whereas gasm and the archaic ideal mode of TASM follow MOV SOURCE, DESTINATION. Furthermore the addressing modes of gasm are really exceptional as compared with the rest of intel assembly world.

To cut this long story short, I would use NASM to learn assembly programming from ground up.

-- tesu

cheers, i already installed both YASM and NASM which im currently looking for tutorials for.

i found out what the assembler need to do 32 bit, but don't know the 'ld' one to get it to make a 32 bit executable.

also may i ask what are the differences between working in 32 bit and 64 bit. So far i know only the 'movl' should be 'movq', and that register instead of starting with an 'e' they start with an 'r' like 'rax'.

So instead of moving a long around its moving a double, anything else different? I was told that when 16 bit is used you have to do some unique things which aren't done now. Are there any things done in 64 bit that’s not done in 32 bit?

With 64bit you can access more memory and store bigger variables.

The maximum INT (unsigned) for 16bit is 2^16 (65,536), for 32bit it is 2^32 (4,294,967,296) and for 64bit it is 2^64 (1.84467441 * 10^19).

With 64bit, you can't run 16bit code but you can run 32bit code. Errrrr

That's about all I know about 64bit

Wikipedia on x86-64

Please correct me if i'm wrong

found my solution '--32' for the assembler and '-melf_i386' for the linker, add those to the command line of each and it works.

Thanks @WithnoMute it took me 3 hours to find this answer, that example now works.

The command I am using to assemble and link that specific example is:

as --32 -o power.o power.s; ld -melf_i386 -o power power.o

All the dozen of posts Ive seen keep mentioning that if you want to assemble 32-bit assembly code to use the --32 bit option for the GAS assembler. None of them mentioned the -melf_i386 option you must also pass to the linker! Its frustrating how MANY people dont actually put the code in any TRY it before they post any kind of response!

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.