简体   繁体   中英

printf gives segmentation fault?

I am (as you would have already guessed) new to nasm coding and I am trying to code this simple combinatorial program (calculates combinations (nCr)) in nasm assembly analogous to this C code I made:

#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;
}

My imitation assembly code in 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

It kept giving me seg fault so i debugged it:

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)

from what I see, the loops were fine and when i called the printf function it gave me the seg fault.

I've seen in some places that they push the format and then the function and then call it. I tried it but I think I did it wrong. Any advice/ criticism and downright profanity if needed on my code is welcome if you feel its constructive in my improvement.

EDIT: Changed "%f" to "%d" and these are the values in the registers just before the printf call:

(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

I GOT IT!!!!

I DID IT I FINALLY SOLVED IT!!!

anyway here is the thing i used:

Instead of pushing the format as push fmt ,

I instead read the nasm docs, saw some examples and found out that we have to store the format fmt in rdi and the variables in their respective order in rsi , rdx , rcx , r8 and so on.

so I did exactly that and BOOM! pops the answer on execution. MY JOY HAS NO LITERAL BOUNDS

repaired code:

        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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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