调用0x16时出现分段错误
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了调用0x16时出现分段错误相关的知识,希望对你有一定的参考价值。
这是我的nasm代码:
extern printf
%macro print 2
mov rdi, %1
mov rsi, %2
mov rax, 0
call printf
%endmacro
section .data
msg1: db 'Nasm', 0
len1: equ $ - msg1
fmts: db "%s", 10, 0 ; printf format string
fmti: db "%d", 10, 0
section .bss ;Uninitialized data
num resb 5
section .text
global main ; declaring for gcc
main:
push rbp ; save rbp
print fmts, msg1
xor ah, ah
int 0x16
print fmti, [num]
exit:
leave
mov rax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
输出:
[b@l .K]$ nasm test.asm -f elf64 -o test.o && gcc test.o -o test && ./test
Nasm
Segmentation fault (core dumped)
当我更换:
print fmts, msg1
print fmti, [num]
xor ah, ah
int 0x16
然后
[b@l .K]$ nasm test.asm -f elf64 -o test.o && gcc test.o -o test && ./test
Nasm
0
Segmentation fault (core dumped)
int 0x80很有效,但0x16压碎了我的代码。我在fedora 29,英特尔酷睿i5上
int 0x80
int
,sysenter
和syscall
指令是call
指令的特殊变体:
这些指令调用一个特殊的函数,即所谓的“处理程序”。
int 0x80
是用于32位Linux程序的Linux操作系统的处理程序。从64位程序调用int 0x80
(并且您的程序显然是64位)可能有效,但它也可能无法正常工作。
在64位Linux中,您使用syscall
而不是int 0x80
。 exit
系统调用应该(*)看起来像这样:
mov $60, %rax # In 64-bit Linux sys_exit is 60, not 1
mov $0, %rdi # Exit code; this would be %ebx in 32-bit Linux
syscall
int 0x16
是Bios中的处理程序。您只能从16位实模式(**)程序中调用BIOS处理程序。您既不能从32-也不能从64位程序调用此处理程序。
(*)不幸的是,我只编写了32位Linux的汇编程序,所以我不确定这是否正确。
(**)执行16位代码时,CPU支持两种不同的操作模式。 BIOS处理程序仅适用于这两种模式之一。
等待键盘
在Linux中没有明确的键盘功能。
您必须使用termios
函数来切换stdin
文件句柄(文件句柄0)的行为。在汇编程序中,这将通过sys_ioctl
调用完成。
默认行为是Linux按行处理输入(例如,如果按“AB”+“退格”+“CD”+“输入”,Linux将返回“ACD”+“输入”程序)。
默认行为也是sys_read
将等待一些数据可用。使用termios
,您可以通过将所有键盘按下返回到程序和/或sys_read
不会等待输入的方式更改此行为。
然后你打电话给sys_read
从stdin
读。
以上是关于调用0x16时出现分段错误的主要内容,如果未能解决你的问题,请参考以下文章