我正在尝试定义一些在其中调用printf的子例程.一个非常简单的例子如下:
extern printf
LINUX equ 80H
EXIT equ 60
section .data
intfmt: db "%ld", 10, 0
segment .text
global main
main:
call os_return ; return to operating system
os_return:
mov rax, EXIT ; Linux system call 60 i.e. exit ()
mov rdi, 0 ; Error code 0 i.e. no errors
int LINUX ; Interrupt Linux kernel
test:
push rdi
push rsi
mov rsi, 10
mov rdi, intfmt
xor rax, rax
call printf
pop rdi
pop rsi
ret
Run Code Online (Sandbox Code Playgroud)
这里测试只是调用printf,将数字10输出到屏幕.我不希望这个被调用,因为我没有打电话给它.
但是在编译和运行时:
nasm …Run Code Online (Sandbox Code Playgroud) 尝试运行以下程序集程序时:
.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位汇编中的类似程序运行良好.
我只是想编译一些我从书中输入的简单示例代码,GCC给出了上述错误.这是我的代码:
$ cat -n test.cpp
1 #define READ_COMMAND 3
2
3 #define MSG_LENGTH 128
4
5 #include <stdlib.h>
6 #include <stdio.h>
7
8 int main(int argc, char *arg[])
9 {
10 int syslog_command = READ_COMMAND;
11 int bytes_to_read = MSG_LENGTH;
12 int retval;
13 char buffer[MSG_LENGTH];
14
15 asm volatile(
16 "movl %1, %%ebx\n\t"
17 "movl %2, %%ecx\n\t"
18 "movl %3, %%edx\n\t"
19 "movl $103, %%eax\n\t"
20 "int $128\n\t"
21 "movl %%eax, %0"
22 :"=r" (retval)
23 :"m"(syslog_command),"r"(buffer),"m"(bytes_to_read)
24 :"%eax","%ebx","%ecx","%edx"); …Run Code Online (Sandbox Code Playgroud) 大家好。
所以我正在学习汇编。
按照我通常学习的任何新语言的学习步骤,我已经到达了使用程序集的网络。
遗憾的是,情况不太好,因为我在第 0 步几乎失败了,这将获得一个可以开始通信的套接字。
汇编代码应大致等于以下 C 代码:
#include <stdio.h>
#include <sys/socket.h>
int main(){
int sock;
sock = socket(AF_INET, SOCK_STREAM, 0);
}
Run Code Online (Sandbox Code Playgroud)
(让我们忽略它现在没有关闭套接字的事实。)
所以这是我到目前为止所做的:
在某些架构上——例如 x86-64 和 ARM——没有 socketcall() 系统调用;相反,socket(2)、accept(2)、bind(2) 等实际上是作为单独的系统调用实现的。
然而,在系统调用的原始列表中没有这样的调用——据我所知socket(),accept()、bind()、listen()、 等是来自libnet而不是来自内核的调用。这让我很困惑,所以我决定编译上面的C代码并使用strace. 这产生了以下结果:
套接字(PF_INET,SOCK_STREAM,IPPROTO_IP)= 3
虽然这并没有让我更接近于知道它是什么socket() ,但它确实解释了它的论点。对于女巫,我似乎没有找到合适的文档(再次)。我认为PF_INET,SOCK_STREAM,IPPROTO_IP就在被定义<sys/socket.h>,但我grep似乎对他们-ing没有发现使用的东西。所以我决定通过gdb与disass main查找值一起使用来实现它。这给出了以下输出:
汇编代码转储功能主要:0x00000000004004fd …
是否可以使用内联汇编块中的系统调用来编写单个字符?如果是这样,怎么样?它应该看起来像这样的"东西":
__asm__ __volatile__
(
" movl $1, %%edx \n\t"
" movl $80, %%ecx \n\t"
" movl $0, %%ebx \n\t"
" movl $4, %%eax \n\t"
" int $0x80 \n\t"
::: "%eax", "%ebx", "%ecx", "%edx"
);
Run Code Online (Sandbox Code Playgroud)
80美元是ascii中的'P',但是没有返回任何内容.
任何建议非常感谢!
我正在Linux上学习x86_64程序集,我遇到了一些我希望可以解决的冲突信息.一方面,我已经读过,对于syscall参数,你会按照rdi,rsi,rdx等顺序使用寄存器.但另一方面,我读过你使用寄存器rbx,rcx,rdx等.一个人告诉我,这是因为ABI的原因,但我并不完全明白这究竟意味着什么.
所以我想我要问的是,为什么这两种格式和哪种格式适合使用?
谢谢!
当我尝试研究内核的系统调用的返回值时,我找到了描述它们的表,以及我需要将它放在不同的寄存器中以使它们工作.但是,我没有找到任何文档说明我从系统调用获得的返回值是什么.我只是在不同的地方找到我收到的东西将在EAX寄存器中.
结果通常在EAX寄存器中返回.
汇编语言循序渐进: Jeff Duntemann 编写的Linux书籍在他的程序中多次说明:
查看sys_read在EAX中的返回值
复制sys_read返回值以便安全保存
我没有解释任何有关此返回值的网站.有没有互联网资源?或者有人能解释我这个价值观吗?
在符合AMD64标准的体系结构中,地址需要在取消引用之前采用规范形式.
在64位模式中,如果微架构的地址位63到最重要的实现位被设置为全1或全零,则认为地址是规范形式.
现在,当前操作系统和体系结构中最有意义的实现位是第47位.这给我们留下了48位的地址空间.
特别是当启用ASLR时,用户程序可能会收到第47位设置的地址.
如果使用指针标记等优化并且高位用于存储信息,则程序必须确保将第48位至第63位设置回取消引用地址之前的第47位.
但请考虑以下代码:
int main()
{
int* intArray = new int[100];
int* it = intArray;
// Fill the array with any value.
for (int i = 0; i < 100; i++)
{
*it = 20;
it++;
}
delete [] intArray;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
现在考虑的intArray是,说:
0000 0000 0000 0000 0 111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1111 1100
设置it到intArray并增加it一次,并考虑sizeof(int) == …
我一直在寻找汇编教程,我正在尝试运行一个hello world程序.我在Windows上使用Ubuntu上的Bash.
这是集会:
section .text
global _start ;must be declared for linker (ld)
_start: ;tells linker entry point
mov edx,len ;message length
mov ecx,msg ;message to write
mov ebx,1 ;file descriptor (stdout)
mov eax,4 ;system call number (sys_write)
int 0x80 ;call kernel
mov eax,1 ;system call number (sys_exit)
int 0x80 ;call kernel
section .data
msg db 'Hello, world!', 0xa ;string to be printed
len equ $ - msg ;length of the string
Run Code Online (Sandbox Code Playgroud)
我正在使用这些命令来创建可执行文件:
nasm -f elf64 hello.asm -o hello.o
ld …Run Code Online (Sandbox Code Playgroud) 64位CPU(amd64)在兼容模式下支持32位Intel指令.此外,如果ELF头表示它是32位可执行文件,64位Linux安装允许运行包含32位指令的ELF.
我想知道是否可以在ELF中放置一些汇编指令,在程序中间将CPU切换到32位兼容模式(然后再返回)?如果内核不允许这些汇编指令,我们是否可以通过某种方式让内核将已经运行的进程切换到32位?
这主要是出于好奇心的问题,因为我无法真正看到任何用例.
assembly ×7
linux ×7
x86-64 ×5
gcc ×3
system-calls ×3
32bit-64bit ×2
c ×2
nasm ×2
x86 ×2
64-bit ×1
aslr ×1
att ×1
kernel ×1
macos ×1
return-value ×1
sockets ×1
subroutine ×1
syslog ×1