这是我的鼻祖代码:
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
答案 0 :(得分:1)
int 0x80
int
,sysenter
和syscall
指令是call
指令的特殊变体:
这些指令调用一个特殊功能,即所谓的“处理程序”。
int 0x80
是Linux操作系统中用于32位Linux程序的处理程序。从64位程序(您的程序显然是64位)中调用int 0x80
可能有效,但也可能无效。
在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” +“ backspace” +“ CD” +“ enter”,Linux将向程序返回“ ACD” +“ enter”)
默认行为也是sys_read
将等待直到有一些数据可用。使用termios
,您可以通过以下方式更改此行为:将所有键盘按键都返回给程序和/或sys_read
将不等待输入。
然后您致电sys_read
来读取stdin
。