我正在尝试检查是否以编程方式启用虚拟化(AMD-V 或 Intel VT)。我知道 bash命令可以为您提供此信息,但我正在尝试在 C++ 中实现此目的。
就这一点而言,我试图避免使用它std::system来执行 shell 代码,因为该解决方案非常糟糕且不是最佳的。提前致谢!
我有以下代码片段(可以在此处找到要点),其中我尝试对 4 个 int32_t 负值和 4 个 int16_t 值(将符号扩展为 int32_t)之间进行求和。
extern exit
global _start
section .data
a: dd -76, -84, -84, -132
b: dw 406, 406, 406, 406
section .text
_start:
movdqa xmm0, [a]
pmovsxwd xmm2, [b]
paddq xmm0, xmm2
;Expected: 330, 322, 322, 274
;Results: 330, 323, 322, 275
call exit
Run Code Online (Sandbox Code Playgroud)
然而,当通过我的调试器时,我无法理解为什么输出结果与预期结果不同。任何想法 ?
我写了一个函数来漂亮地打印一个数独,当然这个模式可以由一些循环生成,但我不想经历麻烦,所以这就是我想出的(前 5 个格式说明符只是参数) printf 本身被压入堆栈,并且在回车后将被覆盖)。
\n虽然“它可以在我的机器上运行”,但我想知道这是否可以或可以移植到跨架构、编译器、libc 实现等工作?
\n当然,根据目标平台,汇编代码可能需要进行一些调整,并且 printf 推送的参数数量取决于当前的 libc 实现。
\n#define PUSH(x) asm volatile ("push %0" : : "m"(x) :)\n#define POP() asm volatile ("pop %%rax" : : : "rax")\n\nvoid print(void) {\n for (uint8_t i = 1; i <= (9 * 9); ++i) {\n PUSH(sudoku[(9 * 9) - i]);\n }\n\n printf("%hhd%hhd%hhd%hhd%hhd\\r\xe2\x95\x94\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\xa6\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x90\xe2\x95\x97\\n"\n "\xe2\x95\x91 %hhd %hhd %hhd \xe2\x95\x91 %hhd %hhd %hhd \xe2\x95\x91 %hhd %hhd %hhd \xe2\x95\x91\\n"\n "\xe2\x95\x91 %hhd %hhd %hhd \xe2\x95\x91 %hhd %hhd %hhd \xe2\x95\x91 %hhd %hhd %hhd …Run Code Online (Sandbox Code Playgroud) 对于 x86-64,有许多指令集可以加速代码执行。以下是 gcc wiki https://gcc.gnu.org/wiki/FunctionMultiVersioning的列表:
-O2?为了简单起见,我们只说问题是关于 gcc 版本 12(最新的主要版本)。但我想知道我需要做什么 gcc 命令开关/选项,以便我可以看到我的 gcc 版本的功能。
我认为 gcc 选择了“可移植”的东西,所以这可能意味着速度很慢。但这只是我的假设......我想知道这是否意味着像SSE4.2或没有?
在下面的代码中,
int firstFunction(int& refParam)
{
std::cout << "Type of refParam is: " << typeid(refParam).name() << '\n';
return refParam;
}
int secondFunction(int param)
{
std::cout << "Type of param is: " << typeid(param).name() << '\n';
return param;
}
int main()
{
int firstVar{ 1 };
int secondVar{ firstFunction(firstVar) };
int thirdVar{ secondFunction(firstVar) };
}
Run Code Online (Sandbox Code Playgroud)
控制台输出是
int
int
Run Code Online (Sandbox Code Playgroud)
当我检查Godbolt 链接中的汇编代码时。
firstFunction(int&):
push rbp
mov rbp, rsp
mov QWORD PTR [rbp-8], rdi
mov rax, QWORD PTR [rbp-8]
mov eax, DWORD PTR [rax] …Run Code Online (Sandbox Code Playgroud) 这些是MOV来自Intel\xc2\xae 64 和 IA-32 架构软件开发人员手册的指令操作码:
B8+ rd id MOV r32, imm32 OI Valid Valid Move imm32 to r32。
C7 /0 id MOV r/m32, imm32 MI Valid Valid Move imm32 to r/m32。
我拆解如下:
\n0: b8 44 33 22 11 mov eax, 0x11223344\nRun Code Online (Sandbox Code Playgroud)\n0: 67 c7 00 44 33 22 11 mov DWORD PTR[eax], 0x11223344\nRun Code Online (Sandbox Code Playgroud)\n我想问的问题是:
\n为什么C7操作码是寄存器/内存(r/m32, imm32)而不是仅内存(m32, imm32)?
是否有任何时候我们使用 …
进行一些基本的反汇编,并注意到由于某种原因,缓冲区被给予了额外的缓冲区空间,尽管我在教程中看到的内容使用相同的代码,但仅给出了正确的(500)个字符长度。为什么是这样?
我的代码:
#include <stdio.h>
#include <string.h>
int main (int argc, char** argv){
char buffer[500];
strcpy(buffer, argv[1]);
return 0;
}
Run Code Online (Sandbox Code Playgroud)
用GCC编译,反汇编代码为:
0x0000000000001139 <+0>: push %rbp
0x000000000000113a <+1>: mov %rsp,%rbp
0x000000000000113d <+4>: sub $0x210,%rsp
0x0000000000001144 <+11>: mov %edi,-0x204(%rbp)
0x000000000000114a <+17>: mov %rsi,-0x210(%rbp)
0x0000000000001151 <+24>: mov -0x210(%rbp),%rax
0x0000000000001158 <+31>: add $0x8,%rax
0x000000000000115c <+35>: mov (%rax),%rdx
0x000000000000115f <+38>: lea -0x200(%rbp),%rax
0x0000000000001166 <+45>: mov %rdx,%rsi
0x0000000000001169 <+48>: mov %rax,%rdi
0x000000000000116c <+51>: call 0x1030 <strcpy@plt>
0x0000000000001171 <+56>: mov $0x0,%eax
0x0000000000001176 <+61>: leave
0x0000000000001177 <+62>: ret
Run Code Online (Sandbox Code Playgroud)
然而,这个视频 …
这是 C 代码:
int baz(int a, int b)
{
return a * 11;
}
Run Code Online (Sandbox Code Playgroud)
它被编译为以下一组汇编指令(带有 -O2 标志):
baz(int, int):
lea eax, [rdi+rdi*4]
lea eax, [rdi+rax*2]
ret
Run Code Online (Sandbox Code Playgroud)
该lea指令计算第二个操作数(源操作数)的有效地址并将其存储在第一个操作数中。对我来说,第一条指令似乎应该将地址加载到 EAX 寄存器,但是,如果是这样,在第二条指令中将 RAX 乘以 2 没有意义lea,所以我推断这两lea条指令不会做完全相同的事情。
我想知道是否有人可以澄清这里到底发生了什么。
.asciix86 汇编中的指令如何工作?什么时候将 ASCII 码放入内存?我假设文本是放置在主内存中的机器代码的一部分,但是这里机器代码的yourText部分到底做了什么?
在 40100e 中, yourText代码部分的开头被放入 write 系统调用的缓冲区参数中。在 CI 中,会将其解释为将指针传递给字符串文字的第一个字符,但我不完全明白为什么它会转到更多代码,而不是在内存中找到文字的位置。
hwa.out: file format elf64-x86-64
Disassembly of section .text:
0000000000401000 <_start>:
401000: 48 c7 c0 01 00 00 00 mov $0x1,%rax
401007: 48 c7 c7 01 00 00 00 mov $0x1,%rdi
40100e: 48 c7 c6 2a 10 40 00 mov $0x40102a,%rsi
401015: 48 c7 c2 0d 00 00 00 mov $0xd,%rdx
40101c: 0f 05 syscall
40101e: 48 c7 c0 3c 00 00 00 mov $0x3c,%rax
401025: …Run Code Online (Sandbox Code Playgroud) 我正在尝试打印 x86-64 中的汇编程序中存在的命令行参数的数量。
据我了解,参数信息存储在堆栈中。
我觉得我缺少一些关于如何检索堆栈中存储的项目的基本知识,但我不知道到底是什么。
.file "args.s"
.globl main
.type main, @function
.section .data
format_string:
.string "Argument: %s\n"
.section .text
main:
pushq %rbp
movq %rsp, %rbp
popq %rsp ; get argc
movq %rsp, %rdi ; move argc to rdi, first parameter register
movq $format_string, %rdi ; pass in the string to be used and give the parameter
call printf
leave
ret
.size main, .-main
Run Code Online (Sandbox Code Playgroud) x86-64 ×10
assembly ×7
c ×3
gcc ×3
c++ ×2
command-line ×1
disassembly ×1
intel ×1
linux ×1
machine-code ×1
opcode ×1
reference ×1
simd ×1
sse ×1
stack ×1
stack-memory ×1