Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
620 views
in Technique[技术] by (71.8m points)

x86 - Assembly - How to multiply/divide a constant by another constant in assembly?

So, I have an assembly function, which is called in C. It compiles and gives me no warnings, but when I try to run it, it gives me a segmentation fault. I think it's because I can't move a constant into a register, but to use the mul/div command it requires a value to be in EAX register. How can I multiply or divide two constants in Assembly?

Here's the code so far...

.section .data
.global n
.equ A, 50
.equ B, 5

.section .text
.global loop_function

loop_function:
    # prologue
    pushl %ebp      # save previous stack frame pointer
    movl %esp, %ebp  # the stack frame pointer for sum function
    # beginning 
    movl i, %ebx # place i (declared in c) in ebx
    movl A, %eax # place A in eax
    movl B, %ecx # place B in ecx
    jmp loop
loop:
    movl $0, %edx # clean edx register
    cdq
    idivl %ecx # A / B, result in eax
    imull %ebx # i * A / B, result in eax

    incl %ebx 
    cmpl %ebx, n # if i <= n
    jle loop # then jumps to loop
    jmp end # else jumps to end

end:
    # epilogue
    movl %ebp, %esp  #  restore the previous stack pointer ("clear" the stack)
    popl %ebp     #  restore the previous stack frame pointer
    ret
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

GAS supports the * operators for assemble-time multiplication of constants. For example, mov $(5 * 50), %eax assembles to exactly the same machine code as mov $250, %eax. Other operators like + - / %, and bitwise stuff are also available. I'll just use * for the examples, but you can construct arbitrary expressions out of compile-time constants as long as they evaluate to a single number (or offset from a symbol that the linker can resolve).

This works with assembler constants like .equ A, 50 or A = 50 as well.

.equ A, 50
.equ B, 5

aa = 3
bb = 7

.globl _start
_start:                    # machine code         .intel_syntax disassembly
    mov $(5 * 50), %eax    # b8 fa 00 00 00    mov  eax,0xfa  # 250

    mov $(aa * B), %ecx    # b9 0f 00 00 00    mov  ecx,0xf   # 3*5 = 15
    mov $A * B,    %edx    # ba fa 00 00 00    mov  edx,0xfa  # 250

Note that the whole immediate constant only uses one $, rather than a $ on every symbol name. For example, mov $(5 + $A), %eax tries to put the address of a symbol called $A (plus 5) into %eax, so you get a link-time error for an undefined symbol.

mov $( $A * $B ), %eax doesn't even assemble:
Error: invalid operands (*UND* and *UND* sections) for '*'
This is because you're trying to multiply the address of two unknown symbols ($A and $B), rather than your assembler constants A and B.

In GAS, all symbols have an associated section. When you define a symbol with .equ or =, it's an "absolute" symbol (rather than a .data section or .text section symbol like you'd get from a label like A:).

Assembler constants aren't really different from symbols defined with labels. However, other than + and -, all assemble-time math operators require both args to be absolute, and the result is absolute.


Your code appears to be trying to put the constants into registers to multiply them at runtime. If you insist on doing that as an exercise,

mov   $A, %ecx           # put symbol's value in ECX
imul  $B, %ecx, %eax     # EAX = A * B

mov A, %eax is a load from the symbol's value. i.e. a load from absolute address 50, which obviously segfaults. Single-step with a debugger and look at the disassembly to understand what happened.

AT&T syntax uses $ for immediate constants, so use that to get the value. (Remember, .equ symbols behave the same as labels, like how you'd use $my_string to get the address as an immediate.)


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...