自己写MBR的时候,需要告诉nasm用16bit汇编,不知道为什么2020年一定要用16bit汇编来写bootloader。
为什么我们不能用现代 x64 程序集开发引导加载程序?
这是来自 musl 的源代码:
1 __syscall_cp_asm:
2 __cp_begin:
3 mov (%rdi),%eax
4 test %eax,%eax
5 jnz __cp_cancel
6 mov %rdi,%r11
7 mov %rsi,%rax
8 mov %rdx,%rdi
9 mov %rcx,%rsi
10 mov %r8,%rdx
11 mov %r9,%r10
12 mov 8(%rsp),%r8
13 mov 16(%rsp),%r9
14 mov %r11,8(%rsp)
15 syscall
16 __cp_end:
17 ret
18 __cp_cancel:
19 jmp __cancel
Run Code Online (Sandbox Code Playgroud)
我很好奇第 6 行和第 14 行的目的是什么(从链接的来源重新编号)。
根据我的理解,代码的开头测试了作为第一个参数传递的指针的目标(第 3-5 行),然后第 6 行将指针移动到r11,第 14 行然后将它移动到使用的堆栈上的位置传递第 7 个参数。
这似乎没有用。这些动作有什么作用吗?
我想使用 NASM 构建自定义便携式可执行文件。使用命令获取可执行文件后,nasm -f bin program.asm -o program.exe它崩溃并给出类似于此的错误
你可以在下面看到代码。
bits 64
%define BASE 400000h
ALIGNMENT equ 512
%define SECTALIGN 8192
STD_OUTPUT_HANDLE equ -11
NULL equ 0
%define ROUND(v, a) (((v + a - 1) / a) * a)
%define ALIGNED(v) (ROUND(v, ALIGNMENT))
%define RVA(obj) (obj - BASE)
section header progbits start=0 vstart=BASE
mz_hdr:
dw "MZ" ; DOS magic
times 0x3a db 0 ; [UNUSED] DOS header
dd RVA(pe_hdr) ; address of PE header
pe_hdr:
dw "PE",0 ; PE …Run Code Online (Sandbox Code Playgroud)
我正在调试一个带有修改过的boringssl 的chrome。它总是有一个SegmentFault。我发现问题是
EC_GROUP_get_curve_name(EC_KEY_get0_group(ec));
Run Code Online (Sandbox Code Playgroud)
反汇编代码:
callq EC_KEY_get0_group
mov %eax,%edi
callq EC_GROUP_get_curve_name
Run Code Online (Sandbox Code Playgroud)
的返回类型EC_KEY_get0_group是一个EC_GROUP*指针,但它是EC_GROUP_get_curve_name由一个 32 位寄存器传递给的。
指针被截断并导致 SegmentFault。为什么编译器会生成这样的代码?是否有任何编译器选项可以避免这种情况?
我在这里有这个 Assembly 函数,并且多次运行它试图了解它的作用和模式是什么。在理解它的模式方面,我遇到了砖墙。任何形式的指导在这里都值得赞赏。
0x0000555555555cbe <+0>: push %rbx
0x0000555555555cbf <+1>: mov %edx,%eax
0x0000555555555cc1 <+3>: sub %esi,%eax
0x0000555555555cc3 <+5>: mov %eax,%ebx
0x0000555555555cc5 <+7>: shr $0x1f,%ebx
0x0000555555555cc8 <+10>: add %eax,%ebx
0x0000555555555cca <+12>: sar %ebx
0x0000555555555ccc <+14>: add %esi,%ebx
0x0000555555555cce <+16>: cmp %edi,%ebx
0x0000555555555cd0 <+18>: jg 0x555555555cda <func4+28>
0x0000555555555cd2 <+20>: cmp %edi,%ebx
0x0000555555555cd4 <+22>: jl 0x555555555ce6 <func4+40>
0x0000555555555cd6 <+24>: mov %ebx,%eax
0x0000555555555cd8 <+26>: pop %rbx
0x0000555555555cd9 <+27>: retq
0x0000555555555cda <+28>: lea -0x1(%rbx),%edx
0x0000555555555cdd <+31>: callq 0x555555555cbe <func4>
0x0000555555555ce2 <+36>: add %eax,%ebx
0x0000555555555ce4 <+38>: jmp …Run Code Online (Sandbox Code Playgroud) 我在汇编中的函数指针有问题,即使我的函数返回一个负数,它总是设置rax为一个正数,我做了一个最小的可重现示例,它使用一个比较两个整数的函数,它做同样的事情:
ASM 功能代码 [编辑]:
global foo
section .data
msg: db `superior\n`
msg_len: equ $-msg
section .text
foo:
push rbx
mov rbx, rdi
mov rdi, 2
mov rsi, 1
sub rsp, 8 ; align the stack frame
call rbx
add rsp, 8
test rax, rax ;[EDIT] correct: test eax, eax
js bar
mov rax, 1
mov rdi, 1
mov rsi, msg
mov rdx, msg_len
syscall
bar:
mov rdi, 1
mov rsi, 2
sub rsp, 8 ; same here
call …Run Code Online (Sandbox Code Playgroud) 堆栈对齐在 ASMx64 中是如何工作的?什么时候需要在函数调用前对齐堆栈,需要减去多少?
我不明白这样做的目的是什么。我知道还有其他关于这个的帖子,但对我来说还不够清楚。例如:
extern foo
global bar
section .text
bar:
;some code...
sub rsp, 8 ; Why 8 (I saw this on some posts) ? Can it be another value ? Why do we need to substract?
call foo ; Do we need to align stack everytime we call a function?
add rsp, 8
;some code...
ret
Run Code Online (Sandbox Code Playgroud) assembly x86-64 calling-convention memory-alignment stack-pointer
我正在设计一个带前缀的可变长度整数。
Rust 有计算前导和尾随 1 和 0 的方法:https : //doc.rust-lang.org/std/primitive.u64.html#method.leading_zeros
这些方法在 x86_64、arm32 和 arm64 上的效率有什么不同吗?
例如,如果计算尾随的 1 比尾随的零更快,我将使用 xxxx0111 而不是 xxxx1000 作为长度编码字节(在本例中,对于后面的三个字节)。
像https://uops.info/和 Agner Fog 的指令表,甚至英特尔自己的手册这样的网站,都列出了相同指令的各种形式。例如add m, r(在 Agner 的表格中)或add (m64, r64)在 uops.info 上,或ADD r/m64, r64在英特尔的手册中(https://www.felixcloutier.com/x86/add)。
这是我在 Godbolt 上运行的一个简单示例
__thread int a;
void Test() {
a+=5;
}
Run Code Online (Sandbox Code Playgroud)
添加是add DWORD PTR fs:0xfffffffffffffffc,0x5。它以操作码开头64 83 04 25。
有几种方法可以编写我的真实代码,但我想查找这可能需要多少个周期以及其他信息。我怎么找到这个指令的参考?我尝试在https://uops.info/table.html 中输入“add”并检查我的架构。但我不知道哪个条目是正在使用的指令。
现在在这种特定情况下,我猜测操作码是Add m64, r64但我不知道fs:在地址之前使用是否有任何惩罚,或者是否有办法查看操作码,以便我可以确认我正在查看正确的参考
我在 x64 上用汇编编程,我打算在堆栈中推送一个地址。我打算编写push %rsp,但是,由于此指令更改了 的值%rsp,我不确定将推送什么值。
具体来说,如果我运行以下命令:
movq $0x10, %rsp
pushq %rsp
Run Code Online (Sandbox Code Playgroud)
内存地址是否0x8包含0x10或0x8?这个处理器是依赖的还是所有 x64 处理器的标准?
x86-64 ×10
assembly ×9
c ×2
nasm ×2
arm ×1
bootloader ×1
callstack ×1
chromium ×1
disassembly ×1
instructions ×1
machine-code ×1
musl ×1
rust ×1
ssl ×1
varint ×1
x86-16 ×1