我正在尝试编写一个Python脚本来测试我在汇编中针对预期输出编写的各种代码的输出.但是我很难将输出重定向到文件中.我写了以下内容:
extern printf
LINUX equ 80H ; interupt number for entering Linux kernel
EXIT equ 1 ; Linux system call 1 i.e. exit ()
section .data
intfmt: db "%ld", 10, 0
segment .text
global main
main:
push rax
push rsi
push rdi
mov rsi, 10
mov rdi, intfmt
xor rax, rax
call printf
pop rdi
pop rsi
pop rax
call os_return ; return to operating system
os_return:
mov rax, EXIT ; Linux system call 1 i.e. exit ()
mov rbx, …Run Code Online (Sandbox Code Playgroud) 在linux上,例如,我们可以使用OS提供的api(打开/关闭/读/写)直接进行系统调用,也可以使用C语言中的libc提供的功能(fopen等)。
用其他语言如何实现?
edi 是 argc,rsi 是 argv
0x0000000000400535 <+8>: mov %edi,-0x4(%rbp)
0x0000000000400538 <+11>: mov %rsi,-0x10(%rbp)
Run Code Online (Sandbox Code Playgroud)
这里我得到argv指针
(gdb) x/8x $rbp-0x10
0x7ffdb7cac380: 0xb7cac478 0x00007ffd 0x00000000 0x00000003
0x7ffdb7cac390: 0x00000000 0x00000000 0x1f130b45 0x00007ff3
Run Code Online (Sandbox Code Playgroud)
指针0x7ffdb7cac478
所以我的 argv[2] 在这里:
(gdb) x/8x 0x7ffdb7cac478+16
0x7ffdb7cac488: 0xb7cacd8a 0x00007ffd 0x00000000 0x00000000
Run Code Online (Sandbox Code Playgroud)
地址 0x7ffdb7cacd8a
我需要获取argv[2]的地址,所以我想编写这个汇编代码:
伪代码:
x - 从地址 $rbp-0x10 //(指向 argv 的指针)加载 8 个字节
y - 从 x 值+16 加载 8 个字节 //(指向 argv[2] 的指针)
我需要稍后跳转到 y。
如何用 x64 汇编程序编写?我可以使用哪个寄存器来表示 x 和 y?
我希望这是可以理解的。我是初学者。
我在这里问是因为我不知道从哪里开始进行研究。
更新:
尝试过这个:
bits 64
ldr r8, rbp, …Run Code Online (Sandbox Code Playgroud) 我在MAC OSX上,我试图通过程序集调用execve系统调用..他的操作码是59.在linux中我必须将操作码设置为eax,然后将参数设置到其他寄存器中,但在这里我必须将操作码放入eax并将参数从右向左推入堆栈.
所以我需要execve("/ bin/sh",NULL,NULL),我发现某个地方有程序集null = 0,所以我将null放入第二和第三个参数.
global start
section .text
start:
jmp string
main:
; 59 opcode
; int execve(char *fname, char **argp, char **envp);
pop ebx ;stringa
push 0x0 ;3rd param
push 0x0 ;2nd param
push ebx ;1st param
add eax,0x3b ;execve opcode
int 0x80 ;interupt
sub eax,0x3a ; exit opcode
int 0x80
string:
call main
db '/bin/sh',0
Run Code Online (Sandbox Code Playgroud)
当我尝试执行它时说:系统调用错误:12
我编写了一个汇编程序来显示遵循 AT&T 语法的数字的阶乘。但它不起作用。这是我的代码
.text
.globl _start
_start:
movq $5,%rcx
movq $5,%rax
Repeat: #function to calculate factorial
decq %rcx
cmp $0,%rcx
je print
imul %rcx,%rax
cmp $1,%rcx
jne Repeat
# Now result of factorial stored in rax
print:
xorq %rsi, %rsi
# function to print integer result digit by digit by pushing in
#stack
loop:
movq $0, %rdx
movq $10, %rbx
divq %rbx
addq $48, %rdx
pushq %rdx
incq %rsi
cmpq $0, %rax
jz next
jmp loop
next:
cmpq $0, %rsi …Run Code Online (Sandbox Code Playgroud) 当我输入 ld -m elf_i386 -o loop loop.asm 时,我得到标题中所述的错误,知道是什么原因造成的吗?对不起,如果代码看起来很糟糕,对汇编来说相当新。
cr equ 13
lf equ 10
section .bss
numA resb 1
section .text
global _start:
mov [numA],byte 0
call loop1
jmp endend
loop1:
xor cx,cx
mov al, $numA
cmp cx, 0x0A
jle else
inc al
jmp end
else:
dec al
jmp end
end:
mov [$numA], al
inc cx
cmp cx,20
jle loop1
endend:
mov dl,$numA
mov ah,2
int 21h
Run Code Online (Sandbox Code Playgroud) 如何在内联汇编gcc中读取stdin并写入stdout,就像我们在NASM中这样做:
_start:
mov ecx, buffer ;buffer is a data word initialised 0h in section .data
mov edx, 03
mov eax, 03 ;read
mov ebx, 00 ;stdin
int 0x80
;Output the number entered
mov eax, 04 ;write
mov ebx, 01 ;stdout
int 0x80
Run Code Online (Sandbox Code Playgroud)
我尝试从内联汇编中的stdin读取,然后将输入分配给x:
#include<stdio.h>
int x;
int main()
{
asm(" movl $5, %%edx \n\t" "
movl $0, %%ebx \n\t" "
movl $3, %%eax \n\t" "
int $0x80 \n\t "
mov %%ecx,x"
::: "%eax", "%ebx", "%ecx", "%edx");
printf("%d",x);
return 0;
} …Run Code Online (Sandbox Code Playgroud) https://www.cs.fsu.edu/~langley/CNT5605/2017-Summer/assembly-example/assembly.html
我看到如下示例。但是我没有找到系统调用的手册。例如,60 表示退出,1 表示写入。是否有所有系统调用的完整手册(包括调用号和参数的含义)?
global _start
section .text
_start:
; ssize_t write(int fd, const void *buf, size_t count)
mov rdi,1 ; fd
mov rsi,hello_world ; buffer
mov rdx,hello_world_size ; count
mov rax,1 ; write(2)
syscall
; exit(result)
mov rdi,0 ; result
mov rax,60 ; exit(2)
syscall
hello_world: db "Hello World!",10
hello_world_size EQU $ - hello_world
Run Code Online (Sandbox Code Playgroud) 我已经做了这个代码:
global strlen
; int strlen(const char *string);
strlen:
xor rcx, rcx
retry:
cmp byte [rdi + rcx], 0
je result
inc rcx
jmp retry
result:
mov rax, rcx
ret
Run Code Online (Sandbox Code Playgroud)
这就是我测试它的方式:
#include <stdio.h>
int main(int argc, char **argv)
{
char* bob = argv[1];
printf("%i\n", strlen(bob));
return 0;
}
Run Code Online (Sandbox Code Playgroud)
这是一个有效的 strlen,这里没问题,但我注意到我可以rdi在重试块的第一行切换arax而不改变任何东西,我不知道这是否是正常行为。我应该保留哪些值?
据我所知,在CPython的,open()和read()-的API来读取一个文件是用C代码。C代码可能会调用一些C库,该C库知道如何进行系统调用。
像Go这样的语言呢?现在Go本身不是用Go编写的吗?Go会在后台调用C库吗?