I'm following the book Programming from the Ground Up which uses 32-bit GNU Assembler for its programs. My machine, however is 64 bit. I got the first two examples fine by typing them in verbatim. No errors whatsoever. However, the third example didn't compile. I made a few changes (for example, changing the l
suffix to q
for the operations and using the r
prefix instead of the e
prefix) to the third example so that it compiles fine now. Now the problem is that it ends up in an infinite loop.
Here's the code:
power.s
# PURPOSE:
# Program to illustrate how functions work.
# This program will compute the value of
# 2^3 + 5^2 (= 8 + 25 = 33)
# Everything in the main program is stored in
# registers, so the data section doesn't have
# anything.
.section .data
.section .text
.globl _start
_start:
pushq $3 # Push the second argument (the power)
pushq $2 # Push the first argument (the base)
call power # Call the function power
addq $8, %rsp # Move the stack pointer back
pushq %rax # Save the first answer before calling again
pushq $2
pushq $5
call power
addq $8, %rsp # Move the stack pointer back
# The first answer is already in %rax, pop the second answer to %rbx
popq %rbx
# Add the answers together and store the result in %rbx
addq %rax, %rbx
movq $1, %rax
int $0x80
# FUNCTION: power
# PURPOSE: To exponentiate a number to a given power
#
# INPUT:
# 1. The base number.
# 2. The power to raise it to.
#
# OUPTUT: Will give the result as a return value.
#
# NOTES: The power must be positiive.
#
# VARIABLES:
# 1. %rbx - holds the base number
# 2. %rcx - holds the power
# 3. -4(%rbp) - holds the current result
# 4. %rax - used for temporary storage
.type power, @function
power:
pushq %rbp # Save old base pointer
movq %rsp, %rbp # Make the stack pointer the base pointer
subq $4, %rsp # Get room for our local storage
movq 8(%rbp), %rbx # The first argument in %rbx
movq 12(%rbp), %rcx # The first argument in %rcx
movq %rbx, -4(%rbp) # The current result
power_loop_start:
cmpq $1, %rcx
je end_power
movq -4(%rbp), %rax # Fetch the last rersult into %rax
imulq %rbx, %rax # Multiply the base with the result and store in %rax
movq %rax, -4(%rbp) # Update the result
decq %rcx # Decrement the power
jmp power_loop_start
end_power:
movq -4(%rbp), %rax # Store return value in %rax
movq %rbp, %rsp # Restore the Stack pointer
popq %rbp # Restore the Base pointer
ret
Any idea as to where it's wrong?
The previous examples which worked just fine:
exit.s
# PURPOSE: Simple program that exits and returns a status code
# back to the Linux kernel.
#
# INPUT: None
#
# OUTPUT: Returns a status code that can be viewed by typing:
# echo $?
# in the terminal after running the program.
#
# VARIABLES:
# %eax holds the system call number
# %ebx holds the return status
.section .data
.section .text
.globl _start
_start:
# This is the Linux kernel command number
# (system call) for exiting a program.
movl $1, %eax
# This is the sattus number we will return
# to the Operating System.
movl $0, %ebx
# This wakes up the kernel to run the exit command
int $0x80
maximum.s
# PURPOSE: This program finds the maximum of a set of
# data items.
#
# VARIABLES: The registers have the following uses.
#
# %edi - Holds the index of the data item being examined.
# %ebx - Largest data item found.
# %eax - The current data item.
#
# The following memory locations are used:
#
# data_items - Contains the data. A '0' terminates the data.
#
.section .data
# The data items go here
data_items:
.long 3,67,34,222,45,75,54,34,44,33,22,11,66,0
.section .text
.globl _start
_start:
movl $0, %edi # Initialize the index register
movl data_items(, %edi, 4), %eax # Load the first (0th) bye of
# data into %eax
movl %eax, %ebx # The first is the max so far
start_loop:
cmpl $0, %eax # See if the current item is 0
je loop_exit
incl %edi # Increment the idex by 1
movl data_items(, %edi, 4), %eax # Load the next item
cmpl %ebx, %eax # Compare the values
jle start_loop
movl %eax, %ebx # The new item is bigger, so
# move it to %ebx
jmp start_loop
loop_exit:
# %ebx is the status code and it has the maximum element
# We'll just return this as the maximum number
movl $1, %eax
int $0x80