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 fmt
、
我反而阅读了 nasm 文档,看到了一些示例,发现我们必须将格式 fmt
存储在 rdi
中,并将变量按各自的顺序存储在 rsi
、rdx
、rcx
、r8
等等。
所以我确实做到了,然后 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
我(正如您可能已经猜到的那样)是 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 fmt
、
我反而阅读了 nasm 文档,看到了一些示例,发现我们必须将格式 fmt
存储在 rdi
中,并将变量按各自的顺序存储在 rsi
、rdx
、rcx
、r8
等等。
所以我确实做到了,然后 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