繁体   English   中英

printf 给出分段错误?

[英]printf gives segmentation fault?

我(正如您已经猜到的)是 nasm 编码的新手,我正在尝试在 nasm 程序集中编写这个简单的组合程序(计算组合 (nCr)),类似于我制作的这个 C 代码:

#include <stdio.h>

int main(int argc, char const *argv[])
{        
    int n = 9;
    int r = 2;
    int i = 0;
    int npr = 1;
    int rfac = 1;
    int k = n;
    //nPr
    while (i<r)
    {
        npr = npr*(k);
        k--;
        i++;
    }
    //r!
    while(r>0)
    {
        rfac = rfac*r;       
        r--;
    }
    //nPr/r! = nCr
    printf("%d\n", npr/rfac);
return 0;
}

我在 nasm 中的仿汇编代码:

        extern printf

        SECTION .data


fmt:    db "%d", 10, 0  ;format for printf (used once)

n:  dq  10              ; 64 bit double var n = 10.000
r:  dq  2               ; 64 bit int var r = 3
i:  dq  0               ; 64 bit int var i = 0
npr:  dq  1             ; 64 bit double var npr = 1.000
rfac:   dq  1           ; 64 bit int var npr = 1


        SECTION .text   ; code section
        global main

main:
        push rbp        ; base pointer
        mov rax,[npr]   ; load npr
        mov rbx,[i]     ; load i
        mov rcx,[n]     ; load n
        mov rdx,[r]     ; load r for condition checking 
        ;sub rdx,[r]     ; subtract n - r
        ;sub rdx,1       ; subtract (n = n-r) - 1. now we can compare it to rdx

        jmp loop1       ; Jump to condition first
cloop1  imul rax,rcx    ; multiply the word npr with n
        dec rcx         ; decrement n
        inc rbx         ; increment i
loop1   cmp rbx,rdx     ; Check the condition
        jl cloop1       ; Jump to content of the loop if met

        mov rdx,[r]     ; load r
        mov rcx,[rfac]  ; load rfac
        mov rbx,0       ; set rbx to 0
        jmp loop2       ; Jump to condition first
cloop2  imul rcx,rdx    ; multiply the word rfac with r
        dec rdx         ; decrement r
loop2   cmp rbx,rdx     ; Check the condition(0<=r)
        jl cloop2       ; Jump to content of the loop if met
diva:   
        mov rdx,0
        mov rax,rax
        idiv rcx        ; divide rax(npr) by rcx(rfac)
        mov rsi,rax     ; 1st printf var
        xor rax,rax     ; make it 0?
        call printf     ; call the function
        
        pop rbp         ; pop the stack
        mov rax,0       ; exit code
        ret             ; return to OS from main

它一直给我段错误所以我调试它:

diva () at ncr.asm:43
43              mov rdx,0
(gdb) info registers
rax            0x5a     90
rbx            0x0      0
rcx            0x2      2
rdx            0x0      0
rsi            0x7ffffffedec8   140737488281288
rdi            0x1      1
rbp            0x400570 0x400570 <__libc_csu_init>
rsp            0x7ffffffedde0   0x7ffffffedde0
r8             0x7fffff3ecd80   140737475693952
r9             0x7fffff3ecd80   140737475693952
r10            0x2      2
r11            0x7      7
r12            0x400400 4195328
r13            0x7ffffffedec0   140737488281280
r14            0x0      0
r15            0x0      0
rip            0x400545 0x400545 <diva>
eflags         0x246    [ PF ZF IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0
(gdb) next
44              mov rax,rax
(gdb) next
45              idiv rcx        ; divide rax(npr) by rcx(rfac)
(gdb) next
46              mov rsi,rax     ; 1st printf var
(gdb) next
47              xor rax,rax     ; make it 0?
(gdb) next
48              call printf     ; call the function
(gdb) next

Program received signal SIGSEGV, Segmentation fault.
__strchrnul_avx2 () at ../sysdeps/x86_64/multiarch/strchr-avx2.S:57
57      ../sysdeps/x86_64/multiarch/strchr-avx2.S: No such file or directory.
(gdb)

从我看来,循环很好,当我调用 printf 函数时,它给了我段错误。

我在某些地方看到他们先推送格式,然后推送函数,然后再调用它。 我试过了,但我认为我做错了。 如果您认为对我的改进有建设性,欢迎对我的代码提出任何建议/批评和彻头彻尾的亵渎(如果需要)。

编辑:将 "%f" 更改为 "%d",这些是 printf 调用之前寄存器中的值:

(gdb) next
48              call printf     ; call the function
(gdb) info registers
rax            0x0      0
rbx            0x0      0
rcx            0x2      2
rdx            0x0      0
rsi            0x2d     45
rdi            0x1      1
rbp            0x400570 0x400570 <__libc_csu_init>
rsp            0x7ffffffedde0   0x7ffffffedde0
r8             0x7fffff3ecd80   140737475693952
r9             0x7fffff3ecd80   140737475693952
r10            0x2      2
r11            0x7      7
r12            0x400400 4195328
r13            0x7ffffffedec0   140737488281280
r14            0x0      0
r15            0x0      0
rip            0x400556 0x400556 <diva+17>
eflags         0x246    [ PF ZF IF ]
cs             0x33     51
ss             0x2b     43
ds             0x0      0
es             0x0      0
fs             0x0      0
gs             0x0      0

我知道了!!!!

我做到了,我终于解决了!!!

无论如何,这是我使用的东西:

而不是将格式push fmtpush fmt

相反,我阅读了 nasm 文档,看到了一些示例,发现我们必须将格式fmt存储在rdi ,并将变量按各自的顺序存储在rsirdxrcxr8等中。

所以我就是这样做的,BOOM! 在执行时弹出答案。 我的快乐没有字面的界限

修复代码:

        extern printf

        SECTION .data


fmt:    db "nCr = %d", 10, 0  ;format for printf (used once)

n:  dq  10              ; 64 bit double var n = 10.000
r:  dq  2               ; 64 bit int var r = 3
i:  dq  0               ; 64 bit int var i = 0
npr:  dq  1             ; 64 bit double var npr = 1.000
rfac:   dq  1           ; 64 bit int var npr = 1


        SECTION .text   ; code section
        global main

main:
        push rbp        ; base pointer
        mov rax,[npr]   ; load npr
        mov rbx,[i]     ; load i
        mov rcx,[n]     ; load n
        mov rdx,[r]     ; load r for condition checking 
        ;sub rdx,[r]     ; subtract n - r
        ;sub rdx,1       ; subtract (n = n-r) - 1. now we can compare it to rdx

        jmp loop1       ; Jump to condition first
cloop1  imul rax,rcx    ; multiply the word npr with n
        dec rcx         ; decrement n
        inc rbx         ; increment i
loop1   cmp rbx,rdx     ; Check the condition
        jl cloop1       ; Jump to content of the loop if met

        mov rdx,[r]     ; load r
        mov rcx,[rfac]  ; load rfac
        mov rbx,0       ; set rbx to 0
        jmp loop2       ; Jump to condition first
cloop2  imul rcx,rdx    ; multiply the word rfac with r
        dec rdx         ; decrement r
loop2   cmp rbx,rdx     ; Check the condition(0<=r)
        jl cloop2       ; Jump to content of the loop if met
diva:   
        mov rdx,0
        mov rax,rax
        idiv rcx        ; divide rax(npr) by rcx(rfac)
        mov rdi,fmt     ; storing format
        mov rsi,rax     ; 1st printf var
        mov rax,0       ; make it 0?        
        call printf     ; call the function
        
        pop rbp         ; pop the stack
        mov rax,0       ; exit code
        ret             ; return to OS from main

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM