你正在寻找这样的东西:
__asm__("divl %2\n"
: "=d" (remainder), "=a" (quotient)
: "g" (modulus), "d" (high), "a" (low));
Run Code Online (Sandbox Code Playgroud)
虽然我同意其他评论者,通常GCC会为你做这件事,你应该尽可能避免内联汇编,有时你需要这个结构.
例如,如果高字小于模数,那么执行这样的除法是安全的.但是,GCC不够聪明才能实现这一点,因为在一般情况下,将64位数字除以32位数会导致溢出,因此它会调用库例程来执行额外的工作.(对于64位ISA,替换为128位/ 64位.)
你不应该试着自己优化它.GCC已经这样做了.
volatile int some_a = 18, some_b = 7;
int main(int argc, char *argv[]) {
int a = some_a, b = some_b;
printf("%d %d\n", a / b, a % b);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
运行
gcc -S test.c -O
Run Code Online (Sandbox Code Playgroud)
产量
main:
.LFB11:
.cfi_startproc
subq $8, %rsp
.cfi_def_cfa_offset 16
movl some_a(%rip), %esi
movl some_b(%rip), %ecx
movl %esi, %eax
movl %esi, %edx
sarl $31, %edx
idivl %ecx
movl %eax, %esi
movl $.LC0, %edi
movl $0, %eax
call printf
movl $0, %eax
addq $8, %rsp
.cfi_def_cfa_offset 8
ret
Run Code Online (Sandbox Code Playgroud)
请注意,余数%edx不会移动,因为它也是传递给printf的第三个参数.
编辑:32位版本不那么令人困惑.传递-m32产生
main:
pushl %ebp
movl %esp, %ebp
andl $-16, %esp
subl $16, %esp
movl some_a, %eax
movl some_b, %ecx
movl %eax, %edx
sarl $31, %edx
idivl %ecx
movl %edx, 8(%esp)
movl %eax, 4(%esp)
movl $.LC0, (%esp)
call printf
movl $0, %eax
leave
ret
Run Code Online (Sandbox Code Playgroud)
幸运的是,您不必使用内联汇编来实现此目的.gcc会尽可能自动执行此操作.
$ cat divmod.c
struct sdiv { unsigned long quot; unsigned long rem; };
struct sdiv divide( unsigned long num, unsigned long divisor )
{
struct sdiv x = { num / divisor, num % divisor };
return x;
}
Run Code Online (Sandbox Code Playgroud)
$ gcc -O3 -std=c99 -Wall -Wextra -pedantic -S divmod.c -o -
.file "divmod.c"
.text
.p2align 4,,15
.globl divide
.type divide, @function
divide:
.LFB0:
.cfi_startproc
movq %rdi, %rax
xorl %edx, %edx
divq %rsi
ret
.cfi_endproc
.LFE0:
.size divide, .-divide
.ident "GCC: (GNU) 4.4.4 20100630 (Red Hat 4.4.4-10)"
.section .note.GNU-stack,"",@progbits
Run Code Online (Sandbox Code Playgroud)
是的——divl 将在 eax 中产生商,在 edx 中产生余数。使用 Intel 语法,例如:
mov eax, 17
mov ebx, 3
xor edx, edx
div ebx
; eax = 5
; edx = 2
Run Code Online (Sandbox Code Playgroud)