Saya (seperti yang sudah Anda duga) baru mengenal pengkodean nasm dan saya mencoba membuat kode program kombinatorial sederhana ini (menghitung kombinasi (nCr)) dalam perakitan nasm yang analog dengan kode C yang saya buat ini:

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

Kode perakitan imitasi saya di 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

Itu terus memberi saya kesalahan seg jadi saya men-debugnya:

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)

Dari apa yang saya lihat, loop baik-baik saja dan ketika saya memanggil fungsi printf itu memberi saya kesalahan seg.

Saya telah melihat di beberapa tempat bahwa mereka mendorong format dan kemudian fungsinya dan kemudian memanggilnya. Saya mencobanya tetapi saya pikir saya salah melakukannya. Setiap saran / kritik dan kata-kata kotor jika diperlukan pada kode saya diterima jika Anda merasa itu konstruktif dalam peningkatan saya.

EDIT: Mengubah "%f" menjadi "%d" dan ini adalah nilai dalam register tepat sebelum panggilan 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
0
mayank 20 November 2020, 13:16

1 menjawab

Jawaban Terbaik

SAYA MENDAPATKANNYA!!!!

SAYA MELAKUKANNYA SAYA AKHIRNYA MEMECAHKANNYA!!!

Lagi pula ini adalah hal yang saya gunakan:

Alih-alih mendorong format sebagai push fmt,

Saya malah membaca dokumen nasm, melihat beberapa contoh dan menemukan bahwa kita harus menyimpan format fmt di rdi dan variabel dalam urutan masing-masing di rsi, rdx ,rcx,r8 dan seterusnya.

Jadi saya melakukan hal itu dan BOOM! muncul jawaban pada eksekusi. KEBAHAGIAAN SAYA TIDAK MEMILIKI BATAS LITERAL

Kode yang diperbaiki:

        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
0
mayank 20 November 2020, 11:52