我正在用C编写一个独立程序,它只依赖于Linux内核.
我研究了相关手册 页,得知X86-64上的Linux系统调用入口点接收通过七个寄存器的系统调用号和六个参数rax,rdi,rsi,rdx,r10,r8,和r9.
这是否意味着 每个系统调用都接受六个参数?
我研究了几个libc实现的源代码,以了解它们如何执行系统调用.有趣的是,musl包含两种不同的系统调用方法:
此汇编源文件定义了一个__syscall函数,该函数将系统调用号和正好六个参数移动到ABI中定义的寄存器.该函数的通用名称暗示它可以与任何系统调用一起使用,尽管它总是将六个参数传递给内核.
此C头文件定义了七个单独的__syscallN函数,并N指定了它们的arity.这表明只传递系统调用所需的确切数量的参数的好处超过了拥有和维护七个几乎相同的函数的成本.
所以我自己尝试了一下:
long
system_call(long number,
long _1, long _2, long _3, long _4, long _5, long _6)
{
long value;
register long r10 __asm__ ("r10") = _4;
register long r8 __asm__ ("r8") = _5;
register long …Run Code Online (Sandbox Code Playgroud) 我在ubuntu下使用nasm.顺便说一下,我需要从用户的键盘上获取单个输入字符(比如一个程序要求你输入y/n?)所以当按下键并且没有按下输入时我需要读取输入的字符.我搜索了很多,但我发现的所有内容都与此行(int 21h)有关,导致"分段错误".请帮我弄清楚如何获得单个字符或如何克服这个分段错误.
我刚开始学习汇编语言.在java中,如果我们有一个Array,我们总是可以使用array.length来获取它的长度.在集会中有这样的事吗?如果是的话,有人可以在这里指导我吗?
编辑:
我很抱歉,我知道程序集没有数组,我试图简化一些事情.
我的意思是,如果我有一个变量
data DB 1,2,3,5,7,8,9,10
Run Code Online (Sandbox Code Playgroud)
鉴于DB可以包含任意数量的元素,我如何检查它包含的总变量?
像java这样的东西,使用int数组来存储它
int data = {1,2,3,4,57,8,9,10};
Run Code Online (Sandbox Code Playgroud)
我们可以只使用data.length来查找元素的总量.
我有一个简单的64位汇编程序,用于打印'O'和'K'后跟换行符.但是,'K'永远不会打印出来.程序的目标之一是将rax寄存器的低位中的值打印为ASCII字母.该程序专门用于64位Linux,用于教育目的,因此不需要使用C风格的系统调用.
我怀疑这个问题要么mov QWORD [rsp], rax或是mov rcx, rsp.
目前,该程序仅输出"O"后跟换行符.
如何更改程序以使其使用rax中的值然后打印"K"以使完整输出为"OK",然后换行?
bits 64
section .data
o: db "O" ; 'O'
nl: dq 10 ; newline
section .text
;--- function main ---
global main ; make label available to the linker
global _start ; make label available to the linker
_start: ; starting point of the program
main: ; name of the function
;--- call interrupt 0x80 ---
mov rax, 4 ; function call: 4
mov rbx, 1 ; …Run Code Online (Sandbox Code Playgroud) 我知道在Linux x64中,“ syscall”和“ int 0x80”汇编程序指令会在软件中生成中断,要求内核执行某些工作。它们具有不同的操作码(0F 05与CD 80),并且前者速度更快。
我不清楚它们之间是否存在任何关系:它们真的独立吗?(即:“ syscall”是否调用“ int 0x80”?)谢谢。
我在 64 位 Linux 环境中运行我的代码,其中 Linux 内核是使用IA32_EMULATION和X86_X32 disabled构建的。
在《从头开始编程》一书中,第一个程序除了产生段错误之外什么都不做:
.section .data
.section .text
.globl _start
_start:
movl $1, %eax
movl $0, %ebx
int $0x80
Run Code Online (Sandbox Code Playgroud)
我将代码转换为使用 x86-64 指令,但它也会出现段错误:
.section .data
.section .text
.globl _start
_start:
movq $1, %rax
movq $0, %rbx
int $0x80
Run Code Online (Sandbox Code Playgroud)
我像这样组装了这两个程序:
as exit.s -o exit.o
ld exit.o -o exit
Run Code Online (Sandbox Code Playgroud)
运行./exit给出了Segmentation fault两个。我究竟做错了什么?
PS 我看过很多用gcc组装代码的教程,但是我想使用gas。
结合评论和答案,这是代码的最终版本:
.section .data
.section .text
.globl _start
_start: …Run Code Online (Sandbox Code Playgroud) 我想了解我们为什么使用int 80h以及在汇编代码中调用它后会发生什么。像这儿:
int 80h
mov eax,1
int 80h
Run Code Online (Sandbox Code Playgroud)
它怎么知道我要调用系统退出,而不只是在eax中保存十进制数?
我希望在汇编程序中编写一个能够发送和接收网络数据包的可启动程序.我不想使用任何库,我想自己创建它(也可以在学习的同时学习).不幸的是,我无法找到有关与最低级别网卡通信的任何信息(发送原始套接字).我认为有必要使用OUT和IN说明,虽然我找不到任何有关分配给网卡的端口的信息(或者如何找到它,如果它不总是相同的话).有人能指出我正确的方向吗?;-)
尝试运行以下程序集程序时:
.globl start
start:
pushq $0x0
movq $0x1, %rax
subq $0x8, %rsp
int $0x80
Run Code Online (Sandbox Code Playgroud)
我收到以下错误:
dyld: no writable segment
Trace/BPT trap
Run Code Online (Sandbox Code Playgroud)
知道是什么原因引起的吗?32位汇编中的类似程序运行良好.
assembly ×8
system-calls ×6
linux ×4
x86-64 ×3
linux-kernel ×2
x86 ×2
32bit-64bit ×1
64-bit ×1
abi ×1
att ×1
c ×1
character ×1
gcc ×1
macos ×1
nasm ×1
networking ×1
raw-sockets ×1
stack ×1
ubuntu ×1