Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/assembly/6.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Assembly 汇编-如何将汇编中的一个常数乘以/除以另一个常数?_Assembly_X86_Constants_Gnu Assembler_Att - Fatal编程技术网

Assembly 汇编-如何将汇编中的一个常数乘以/除以另一个常数?

Assembly 汇编-如何将汇编中的一个常数乘以/除以另一个常数?,assembly,x86,constants,gnu-assembler,att,Assembly,X86,Constants,Gnu Assembler,Att,所以,我有一个汇编函数,它是在C中调用的。它编译并没有给我任何警告,但当我试图运行它时,它给了我一个分段错误。我认为这是因为我不能将常量移动到寄存器中,但要使用mul/div命令,它需要一个值位于EAX寄存器中。 如何在汇编中乘或除两个常量 这是到目前为止的代码 .section .data .global n .equ A, 50 .equ B, 5 .section .text .global loop_function loop_function: # prologue

所以,我有一个汇编函数,它是在C中调用的。它编译并没有给我任何警告,但当我试图运行它时,它给了我一个分段错误。我认为这是因为我不能将常量移动到寄存器中,但要使用mul/div命令,它需要一个值位于EAX寄存器中。 如何在汇编中乘或除两个常量

这是到目前为止的代码

.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
气体支持常数。例如,mov$5*50,%eax汇编成与mov$250,%eax完全相同的机器代码。其他操作符如+-/%和按位填充也可用。我将仅使用*作为示例,但您可以使用编译时常量构造任意表达式,只要它们的计算结果是链接器可以解析的单个数字或符号的偏移量

这也适用于汇编器常量,如.eq A、50或A=50

请注意,整个立即数常量只在每个符号名上使用一个$,而不是一个$。例如,mov$5+$A,%eax尝试将名为$A+5的符号的地址放入%eax,因此未定义的符号会出现链接时间错误

mov$$A*$B,%eax甚至没有组装: 错误:“*”的无效操作数*UND*和*UND*部分 这是因为您试图将两个未知符号$A和$B的地址相乘,而不是将汇编器常量A和B相乘

在气体中。当您使用.eq或=”定义符号时,它是一个绝对符号,而不是一个.data节或.text节符号,就像您从标签中得到的那样:

汇编器常量与用标签定义的符号并没有什么不同。但是,除了+和-,所有

您的代码似乎试图将常量放入寄存器,以便在运行时将它们相乘。如果你坚持这样做是一种锻炼

mov   $A, %ecx           # put symbol's value in ECX
imul  $B, %ecx, %eax     # EAX = A * B
mov A,%eax是来自符号值的负载。i、 e.从绝对地址50加载,这显然会导致故障。使用调试器执行单个步骤,并查看反汇编以了解发生了什么


AT&T语法使用$作为立即数常量,因此使用它来获取值。请记住,.eq符号的行为与标签相同,比如如何使用$my_字符串以立即数形式获取地址。

谢谢大家的帮助,伙计们,我用以下代码完成了练习:

.section .data
    .global n
    .global i
    .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, %ecx # place i (declared in c) in ecx
    movl $A, %eax  # place A in eax
    movl $B, %ebx # place B in ebx
    movl $0, %edx # clean edx register
    cdq
    idivl %ebx # (A / B), result goes to eax
loop:
    incl %ecx # increment i, which is in ecx
    cmpl n, %ecx # if n > i
    jg loop # then jumps to loop
end:
    incl %ecx
    imull %ecx # multiply i by (A / B), result in eax
    # epilogue
    movl %ebp, %esp  #  restore the previous stack pointer ("clear" the stack)
    popl %ebp     #  restore the previous stack frame pointer
    ret

真正的答案在ABI中。如果您没有ABI,那么我建议将您使用的每个寄存器推到堆栈上,并在返回之前弹出它。错误的可能原因是您没有遵循标准调用约定。特别是,您破坏了ebx,它是被调用方保存的寄存器,因此您的调用方很可能希望它保持不变。a和B似乎是常量,我猜我是一个变量,但您对它们使用完全相同的语法。我认为它试图从内存地址50和地址5加载值,这是行不通的。我建议使用$A和$B。如果我在常量声明中放入$50和$5,编译失败,$A给出了常量的内存地址,我想。您将常量声明为内存地址,所以应该使用$A和$B。您尝试过吗?要能够使用,您需要类似以下内容:A:.int 50。您应该将i和n作为函数参数而不是全局参数传递。此外,干熄焦从eax设置edx,因此没有必要先将edx归零。而且,我看不到循环的意义。您可以用mov n,%ecx替换它。或者我猜使用extra inc,您正在执行%ecx=n+1操作,并且您在不保存它的情况下对%ebx进行了重击。使用%ecx为idiv除数保留$B。因此,您的整个函数可以是mov$A,%eax;干熄焦;mov$B,%ecx;idiv%ecx;imul n,%eax。或者将n加载到ecx或edx中,然后inc%ecx(如果实际需要n+1)。您不需要使用单操作数形式,除非您希望在edx:eax中返回完整的64位乘积。2操作数形式更快,只写入一个寄存器。
.section .data
    .global n
    .global i
    .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, %ecx # place i (declared in c) in ecx
    movl $A, %eax  # place A in eax
    movl $B, %ebx # place B in ebx
    movl $0, %edx # clean edx register
    cdq
    idivl %ebx # (A / B), result goes to eax
loop:
    incl %ecx # increment i, which is in ecx
    cmpl n, %ecx # if n > i
    jg loop # then jumps to loop
end:
    incl %ecx
    imull %ecx # multiply i by (A / B), result in eax
    # epilogue
    movl %ebp, %esp  #  restore the previous stack pointer ("clear" the stack)
    popl %ebp     #  restore the previous stack frame pointer
    ret