我正在使用堆栈进行一些实验,以下内容让我陷入困境。
可以看出Linux在大小上有初始[stack]映射132KiB。ulimit -s unlimited如果我们进行相应的调整,我们可以进一步扩展堆栈rsp。所以我设置ulimit -s unlimited并运行了以下程序:
PAGE_SIZE equ 0x1000
;mmap staff
PROT_READ equ 0x01
PROT_WRITE equ 0x02
MAP_ANONYMOUS equ 0x20
MAP_PRIVATE equ 0x02
MAP_FIXED equ 0x10
;syscall numbers
SYS_mmap equ 0x09
SYS_exit equ 0x3c
section .text
global _start
_start:
; page alignment
and rsp, -0x1000
; call mmap 0x101 pages below the rsp with fixed mapping
mov rax, SYS_mmap
lea rdi, [rsp - 0x101 * PAGE_SIZE]
mov rsi, PAGE_SIZE
mov …Run Code Online (Sandbox Code Playgroud) 我正在尝试组装一些 64 位代码,但组装失败了:
addq $0xffffff7fc0005000, %rax
Run Code Online (Sandbox Code Playgroud)
有错误:
`add' 的错误操作数类型不匹配
第一个操作数是一个 64 位值,后者是一个应该组装好的寄存器。该指令前面有一个.code64伪操作。我正在组装
x86_64-elf-as test.s -o test.o --64
Run Code Online (Sandbox Code Playgroud)
至于汇编器本身,当用--version它调用时返回:
GNU assembler (GNU Binutils) 2.32
Copyright (C) 2019 Free Software Foundation, Inc.
This program is free software; you may redistribute it under the terms of
the GNU General Public License version 3 or later.
This program has absolutely no warranty.
This assembler was configured for a target of `x86_64-elf'.
Run Code Online (Sandbox Code Playgroud) 在程序的一部分中,我以两种不同的方式打印出相同的指针。
vpx_codec_iface_t *ptr = vpx_codec_vp9_cx();
printf("ptr1 %p\n", ptr);
printf("ptr2 %p\n", vpx_codec_vp9_cx());
Run Code Online (Sandbox Code Playgroud)
这奇怪地导致以下输出。
ptr1 FFFFFFFFDAF9CED0
ptr2 00000000DAF9CED0
Run Code Online (Sandbox Code Playgroud)
玩弄这个程序,我可以通过添加一些代码或添加一些换行符来“修复”错误。
int x = 0;
vpx_codec_iface_t *ptr = vpx_codec_vp9_cx();
printf("ptr1 %p\n", ptr);
printf("ptr2 %p\n", vpx_codec_vp9_cx());
printf("x=%d\n", x);
Run Code Online (Sandbox Code Playgroud)
这导致以下输出。
ptr1 0000000066A7CED0
ptr2 0000000066A7CED0
x=0
Run Code Online (Sandbox Code Playgroud)
什么可能导致这种行为?我在 Windows 10 上使用 Visual Studio 2019 编译器,为 x64 进行编译。函数调用vpx_codec_vp9_cx()是在vpxmd.lib其中实现的,来自libvpx项目。
编辑:我仍在查看您的答案和评论,但我在下面创建了一个最小示例。不幸的是,它涉及构建整个 vpx 库,因此我需要一些时间来简化该部分。
#include <stdio.h>
#include "vpx/vpx_encoder.h"
int main(int argc, char **argv) {
printf("This is main\n");
vpx_codec_iface_t *ptr = vpx_codec_vp9_cx();
int x = 0;
printf("ptr1 …Run Code Online (Sandbox Code Playgroud) #include <cstdint>
uint64_t hr1(const uint64_t x, const bool a, const int n) noexcept
{
if (a) {
return x | (a << n);
}
return x;
}
uint64_t hr2(const uint64_t x, const bool a, const int n)
{
return x | ((a ? 1ull : 0) << n);
}
Run Code Online (Sandbox Code Playgroud)
hr1(unsigned long, bool, int):
mov rax, rdi
test sil, sil
jne .L4
ret
.L4:
mov ecx, edx
mov esi, 1
sal esi, cl
movsx rsi, esi
or rax, rsi
ret …Run Code Online (Sandbox Code Playgroud) 沉迷于汇编程序的学习
mov byte ptr [rax+rdx-01],00
RAX=00000004
RDX=2295EA3B878
Run Code Online (Sandbox Code Playgroud)
和
mov [r10+rsi],al
RAX=0000000000000065
RSI=000002295EA3B878
R10=0000000000000000
Run Code Online (Sandbox Code Playgroud)
很清楚mov al byte ptr。但我不明白什么意思 [rax+rdx-01]和[r10+rsi] rax 和 r10 不是指针。
在大多数情况下,我面临[RAX+C1]rax 是指针而 C1 是偏移量的情况,但是我不知道寄存器存储某些值而不是指针时的含义
所以AFAIK syscall指令,相当于AMD 的sysenter。所以理论上应该只能在 AMD 芯片上找到一条syscall指令,对吗?好吧,显然情况并非如此,因为我正在处理 ntdll.dll 和 ntdll.dll(WOW64 版本),我发现常规版本使用syscall而来自 WOW64 的 ntdll.dll 使用sysenter。这是为什么?
我正在使用 Buildroot 2020.02.1 为安装了 AMD GX-222GC SOC 的 PC 构建自定义内核。
默认的外部工具链是来自 CodeBench 的 amd-2016.11-19。使用该工具链构建的内核正确启动。 相反,如果我使用由 buildroot 自动构建的工具链构建相同的内核、相同的配置,则内核不会启动!甚至没有内核恐慌,机器只是重置。
很明显,问题与工具链有关。
这些是 gcc -v 的结果
代码台:
$ output/host/usr/bin/x86_64-amd-linux-gnu-gcc -v
Using built-in specs.
COLLECT_GCC=/media/AAA/tmp/buildroot_toolchain/output/host/opt/ext-toolchain/bin/x86_64-amd-linux-gnu-gcc
COLLECT_LTO_WRAPPER=/media/AAA/tmp/buildroot_toolchain/output/host/opt/ext-toolchain/bin/../libexec/gcc/x86_64-amd-linux-gnu/6.2.0/lto-wrapper
Target: x86_64-amd-linux-gnu
Configured with: /scratch/jmyers/amd-lite/src/gcc-6-2016.11/configure --build=i686-pc-linux-gnu --host=i686-pc-linux-gnu --target=x86_64-amd-linux-gnu --enable-threads --disable-libmudflap --disable-libstdcxx-pch --enable-extra-sgxxlite-multilibs --with-arch=btver2 --with-cpu=btver2 --with-gnu-as --with-gnu-ld --with-specs='-D__CS_SOURCERYGXX_MAJ__=2016 -D__CS_SOURCERYGXX_MIN__=11 -D__CS_SOURCERYGXX_REV__=19' --enable-languages=c,c++ --enable-shared --enable-lto --enable-symvers=gnu --enable-__cxa_atexit --with-glibc-version=2.24 --with-pkgversion='Sourcery CodeBench Lite 2016.11-19' --with-bugurl=https://sourcery.mentor.com/GNUToolchain/ --disable-nls --prefix=/opt/codesourcery --with-sysroot=/opt/codesourcery/x86_64-amd-linux-gnu/libc --with-build-sysroot=/scratch/jmyers/amd-lite/install/opt/codesourcery/x86_64-amd-linux-gnu/libc --with-gmp=/scratch/jmyers/amd-lite/obj/pkg-2016.11-19-x86_64-amd-linux-gnu/amd-2016.11-19-x86_64-amd-linux-gnu.extras/host-libs-i686-pc-linux-gnu/usr --with-mpfr=/scratch/jmyers/amd-lite/obj/pkg-2016.11-19-x86_64-amd-linux-gnu/amd-2016.11-19-x86_64-amd-linux-gnu.extras/host-libs-i686-pc-linux-gnu/usr --with-mpc=/scratch/jmyers/amd-lite/obj/pkg-2016.11-19-x86_64-amd-linux-gnu/amd-2016.11-19-x86_64-amd-linux-gnu.extras/host-libs-i686-pc-linux-gnu/usr --with-isl=/scratch/jmyers/amd-lite/obj/pkg-2016.11-19-x86_64-amd-linux-gnu/amd-2016.11-19-x86_64-amd-linux-gnu.extras/host-libs-i686-pc-linux-gnu/usr --enable-libgomp --enable-libitm --enable-libatomic --disable-libssp --disable-libcc1 --enable-poison-system-directories --with-python-dir=x86_64-amd-linux-gnu/share/gdb/python --with-build-time-tools=/scratch/jmyers/amd-lite/install/opt/codesourcery/x86_64-amd-linux-gnu/bin --with-build-time-tools=/scratch/jmyers/amd-lite/install/opt/codesourcery/x86_64-amd-linux-gnu/bin SED=sed …Run Code Online (Sandbox Code Playgroud) 由于 ?x = not(x)+1 则意味着 ab = a+not(b)+1,那么
sub rax, rcx
Run Code Online (Sandbox Code Playgroud)
相当于
mov temp, rcx
not temp
add rax, temp
add rax, 1
Run Code Online (Sandbox Code Playgroud)
temp 某些寄存器被认为是易失性的?
换句话说,后者是否以完全相同的方式影响 EFLAGS?如果不是,又怎么能强求呢?
为什么从 float max 中减去 1 会返回一个合理的值,而向 float min 中加 1 会返回 1?
我认为,如果您添加或减去一个小于该特定量级的 epsilon 的值,则不会发生任何事情,也不会增加或减少。
这是我用没有标志的 g++ 编译并在 x86_64 上运行的代码。
#include <limits>
#include <iostream>
int main() {
float min = std::numeric_limits<float>::min() + 1;
float max = std::numeric_limits<float>::max() - 1;
std::cout << min << std::endl << max << std::endl;
return 0;
}
Run Code Online (Sandbox Code Playgroud)
输出这个:
1
3.40282e+38
Run Code Online (Sandbox Code Playgroud)
我希望它输出这个:
-3.40282e+38
3.40282e+38
Run Code Online (Sandbox Code Playgroud) 我们知道,根据 x86-64 约定,寄存器%rbx、%rbp和%r12–%r15被归类为被调用者保存的寄存器。While%r10和%r111是调用者保存的寄存器。但是当我在大多数情况下编译 C 代码时,例如函数P调用Q,我看到以下函数的汇编代码Q:
Q:
push %rbx
movq %rdx, %rbx
...
popq %rbx
ret
Run Code Online (Sandbox Code Playgroud)
我们知道,由于%rbx是一个被调用者保存的寄存器,我们必须将它存储在堆栈中,并在P以后为调用者恢复它。
但它不会更简洁并通过使用调用者保存的寄存器来保存堆栈操作%r10:
Q:
movq %rdx, %r10
...
ret
Run Code Online (Sandbox Code Playgroud)
所以被调用者不需要担心保存和恢复调用者的寄存器,因为调用者在调用被调用者之前已经把它推到了堆栈?