分段错误并挂在汇编代码中

segmentation fault and hang in assembly code

我正在重新实现分册 1 中 Knuth 的程序 P:生成前 500 个素数。该程序毫无问题地生成了前 25 个素数。该代码如下:

$ cat progp.S
/* print the first 500 primes */

#define n       %bx
#define j       %r12
#define k       %r13
#define pk      %r14d

        .data
fmt:    .asciz  "%d\n"
x:      .space 1000

        .text
        .globl  main
        .type   main, @function
main:
        pushq   %rbp
        movq    %rsp, %rbp
        xorq    %rbx, %rbx
        movw    , x
        movw    , n
        movq    , j
Mtwo:
        movw    n, x(,j,2)
        incq    j
Mthree:
        cmpq    0, j
        je      end
Mfour:
        addw    , n
Mfive:
        movq    , k
Msix:
        movzwl  x(,k,2), pk
        movzwl  n, %eax
        xorq    %rdx, %rdx
        divl    pk
        cmpl    [=10=], %edx
        je      Mfour
Mseven:
        cmpl    pk, %eax
        jle     Mtwo
Meight:
        incq    k
        jmp     Msix
end:
        xorq    j, j
loop:
        leaq    fmt, %rdi
        movzwl  x(,j,2), %esi
        call    printf
        incq    j
        cmpq    , j
        je      bye
        jmp     loop
bye:
        movl    [=10=], %edi
        callq   exit
        leave
        ret
        .size   main,.-main
        .end

如果将 Mthree 中的比较减少到 25,那么程序就可以了。任何更高的值,程序都会在 printf 中出错或挂起。

我正在组装它:

cc -static progp.S

我还可以补充一点,在不调用 printf 的情况下,它成功生成了前 500 个素数,这可以从 gdb 中的 "end" 处放置断点看出。

$ gdb ./a.out
(gdb) b end
Breakpoint 1 at 0x400531
(gdb) run
Starting program: /home/ben/src/hg/asm/knuth/a.out 

Breakpoint 1, 0x0000000000400531 in end ()
(gdb) p $rbx
 = 3571

我一尝试调用 printf,它就出错了,所以我假设我对堆栈做了一些愚蠢的事情。

printf 在 x86-64 中期望 %rax 中的一个值告诉函数浮点参数的数量。在你的情况下没有这样的参数,所以清楚 %rax(清除 %eax 也清除 %rax)。您的程序似乎 运行 可以接受更改:

...
loop:
        leaq    fmt, %rdi
        movzwl  x(,j,2), %esi
        xor     %eax, %eax
        call    printf
...