0

Entire code is:

# Purpose: a program that shows how functions work
# This program will calculate
# 2 ^ 3 + 5 ^ 2

# All contents of the main program are stored in registers,
# Therefore, the data segment does not contain any content
.code32
.section .data

.section .text

.globl _start
_start:
    pushl $3    # Press in the second parameter
    pushl $2    # Press in the first parameter
    call power  # Call function
    addl $8,%esp    # Move the stack pointer backward
    pushl %eax  # Saves the return value from the first call before calling the next function
    

    pushl $2    # Press in the second parameter
    pushl $5    # Press in the first parameter
    call power  # call function
    addl $8,%esp   # Moves the stack pointer backward
    popl %ebx   # The return value from the second call is already in %eax,
                # Now pop the return value from the first call into %ebx
    
    addl %eax,%ebx  # Add the two, and the result is in %ebx

    movl $1,%eax    # quit
    int $0x80

# Purpose: This function is used to calculate the power of a number
#
# Input: first parameter - base number
# Second parameter - the exponent of the base
#
# Output: The result is given as a return value
#
# variables:
# % ebx - Save base number
# % ecx - Save index
#
# -4(%ebp) - Save the current result
#
# %eax for temporary storage
#
.type power,@function
power:
    pushl %ebp      # Retain the old base address pointer
    movl %esp,%ebp  # Set the base pointer to the stack pointer
    subl $4,%esp    # Reserve space for local storage

    movl 8(%ebp),%ebx   # Put the first argument in %ebx
    movl 12(%ebp),%ecx  # Put the second argument in %ecx

    movl %ebx,-4(%ebp)  # Storing the current result

power_loop_start:
    cmpl $1,%ecx    # If it's to the first power, then we've got the result
    je end_power
    movl -4(%ebp),%eax  # Moves the current result into %eax
    imull %ebx,%eax     # Multiply the current result by the base
    movl %eax,-4(%ebp)  # Save the current result

    decl %ecx           # exponential decrease
    jmp power_loop_start    # Power calculation for the decreasing exponent

end_power:
    movl -4(%ebp),%eax  # Return value moved to %eax
    movl %ebp,%esp      # Recovery stack pointer
    popl %ebp           # Restore the base address pointer
    ret

I'm running in x86_64, and at compile time I get this message:

$ as power.s -o power.o
power.s: Assembler messages:
power.s:14: error: invalid instruction suffix for `push'
power.s:15: error: invalid instruction suffix for `push'
power.s:18: error: invalid instruction suffix for `push'
power.s:21: error: invalid instruction suffix for `push'
power.s:22: error: invalid instruction suffix for `push'
power.s:25: error: invalid instruction suffix for `pop'
power.s:50: error: invalid instruction suffix for `push'
power.s:72: error: invalid instruction suffix for `pop'

So I added ".code32 ", the problem was solved, and I could compile and link smoothly, but during the run, there was an error again. I used GDB to trace, and the error message was as follows:

For help, type "help".
Type "apropos word" to search for commands related to "word"...
Reading symbols from power...
(No debugging symbols found in power)
(gdb) run
Starting program: /github/assembly/04/power 

Program received signal SIGSEGV, Segmentation fault.
0x0000000000401029 in power ()
(gdb) bt
#0  0x0000000000401029 in power ()
Backtrace stopped: Cannot access memory at address 0xffffdfd4
(gdb) frame 0
#0  0x0000000000401029 in power ()
(gdb) info f
Stack level 0, frame at 0xffffdfdc:
 rip = 0x401029 in power; saved rip = <not saved>
 Outermost frame: Cannot access memory at address 0xffffdfd4
 Arglist at 0xffffdfcc, args: 
 Locals at 0xffffdfcc, Previous frame's sp is 0xffffdfdc
Cannot access memory at address 0xffffdfcc
(gdb) i register
rax            0x0                 0
rbx            0x0                 0
rcx            0x0                 0
rdx            0x0                 0
rsi            0x0                 0
rdi            0x0                 0
rbp            0xffffdfd0          0xffffdfd0
rsp            0xffffdfcc          0xffffdfcc
r8             0x0                 0
r9             0x0                 0
r10            0x0                 0
r11            0x0                 0
r12            0x0                 0
r13            0x0                 0
r14            0x0                 0
r15            0x0                 0
rip            0x401029            0x401029 <power+6>
eflags         0x10296             [ PF AF SF IF RF ]
--Type <RET> for more, q to quit, c to continue without paging--
cs             0x33                51
ss             0x2b                43
ds             0x0                 0
es             0x0                 0
fs             0x0                 0
gs             0x0                 0
(gdb) 

After I disassemble the code, it looks like this:

$ objdump -d power

power:     file format elf64-x86-64


Disassembly of section .text:

0000000000401000 <_start>:
  401000:       6a 03                   pushq  $0x3
  401002:       6a 02                   pushq  $0x2
  401004:       e8 1a 00 00 00          callq  401023 <power>
  401009:       83 c4 08                add    $0x8,%esp
  40100c:       50                      push   %rax
  40100d:       6a 02                   pushq  $0x2
  40100f:       6a 05                   pushq  $0x5
  401011:       e8 0d 00 00 00          callq  401023 <power>
  401016:       83 c4 08                add    $0x8,%esp
  401019:       5b                      pop    %rbx
  40101a:       01 c3                   add    %eax,%ebx
  40101c:       b8 01 00 00 00          mov    $0x1,%eax
  401021:       cd 80                   int    $0x80

0000000000401023 <power>:
  401023:       55                      push   %rbp
  401024:       89 e5                   mov    %esp,%ebp
  401026:       83 ec 04                sub    $0x4,%esp
  401029:       8b 5d 08                mov    0x8(%rbp),%ebx
  40102c:       8b 4d 0c                mov    0xc(%rbp),%ecx
  40102f:       89 5d fc                mov    %ebx,-0x4(%rbp)

0000000000401032 <power_loop_start>:
  401032:       83 f9 01                cmp    $0x1,%ecx
  401035:       74 0c                   je     401043 <end_power>
  401037:       8b 45 fc                mov    -0x4(%rbp),%eax
  40103a:       0f af c3                imul   %ebx,%eax
  40103d:       89 45 fc                mov    %eax,-0x4(%rbp)
  401040:       49 eb ef                rex.WB jmp 401032 <power_loop_start>

0000000000401043 <end_power>:
  401043:       8b 45 fc                mov    -0x4(%rbp),%eax
  401046:       89 ec                   mov    %ebp,%esp
  401048:       5d                      pop    %rbp
  401049:       c3                      retq  

I have checked the logic of the assembly code and found no error. If you know the answer, please let me know. Thank you very much!

  • The `.code32` directive is almost always wrong. It changes how the assembler assembles your code, but the processor still expects 64 bit code in a 64 bit binary. If you give it 32 bit code instead, weird things are going to happen. Instead, you need to provide appropriate arguments to your toolchain to make it assemble and link for 32 bit. – fuz Aug 25 '21 at 06:52

0 Answers0