我目前正在开发一个 BIOS 引导加载程序,我对汇编比较陌生,我一直在阅读它,我了解它是如何工作的,但有一些事情我不明白,涉及我的汇编代码的执行顺序。
所以基本上我的子例程 _print 是如何被调用的,即使我没有调用它。其次,如果BIOS幻数一直在文件末尾,即使我没有到达,它是如何分配的。
我将不胜感激任何帮助,谢谢。
[ORG 0000:7C00]
global _start
_print:
mov ah, 0x0e
mov al, '['
int 0x10
mov al, '+'
int 0x10
mov al, '['
int 0x10
ret
_start:
jmp $
times 510 - ($-$$) db 0
dw 0xAA55
Run Code Online (Sandbox Code Playgroud) 在这个简单的函数中,为局部变量分配了空间。然后,变量被初始化并被printf调用以输出它们。
000000000040056a <func>:
40056a: 55 push rbp ; function prologue
40056b: 48 89 e5 mov rbp,rsp ; function prologue
40056e: 48 83 ec 10 sub rsp,0x10 ; deallocating space for local variables
400572: 8b 4d fc mov ecx,DWORD PTR [rbp-0x4] ; variable initialization
400575: 8b 55 f8 mov edx,DWORD PTR [rbp-0x8] ; variable initialization
400578: 8b 45 f4 mov eax,DWORD PTR [rbp-0xc] ; variable initialization
40057b: 89 c6 mov esi,eax ; string stuff
40057d: bf 34 06 40 …Run Code Online (Sandbox Code Playgroud) 我正在用 c 语言编写一个国际象棋引擎,速度至关重要。国际象棋引擎基于 unsigned long long,我将其表示为 u64,并且它严重依赖于最低有效位扫描。到目前为止,我一直在使用 gcc 函数 __builtin_ctzll ,它做得很好。然而,我使用 gcc -S -O2 为这个独立函数生成了汇编代码。它给了我以下内容:
xorl %eax, %eax
rep bsfq %rdi, %rax
cltq
ret
Run Code Online (Sandbox Code Playgroud)
然而经过一番调查似乎代码
rep bsfq %rdi, %rax
ret
Run Code Online (Sandbox Code Playgroud)
在我的国际象棋程序中做了完全相同的事情。然而现在速度慢了约 20%。它应该更快,因为它的指令更少。然而,原始的 __builtin_ctzll 内联在我的 C 代码中。这是我的自定义汇编代码运行速度比原始代码慢的原因吗?因为当我声明函数 ctzll 时,我当然不能在 c 中内联声明它,除非我有定义(不在汇编代码中)。
是否有另一种方法来优化汇编指令,或者我应该尝试直接在 c 中内联 asm 的新汇编代码?
我阅读了这两个操作的手册描述,但还不明白其中的区别。有人可以举例说明 shufpd 与 pshufd 的比较吗?
我谈到的例子是cppreference.com 上的这个例子。代码片段粘贴在下面。
int main(){
const std::size_t ThreadNumber = 5;
const int Sum = 5;
std::atomic<int> atom{0};
std::atomic<int> counter{0};
// lambda as thread proc
auto lambda = [&](const int id){
for (int next = 0; next < Sum;){
// each thread is writing a value from its own knowledge
const int current = atom.exchange(next);
counter++;
// sync writing to prevent from interrupting by other threads
std::osyncstream(std::cout)
<< '#' << id << " (" << std::this_thread::get_id()
<< ") wrote " …Run Code Online (Sandbox Code Playgroud) 我是一名大学计算机科学学生,我应该为考试开发一个 MIPS 汇编语言程序,但我确实很难设计它,特别是在分配寄存器、遵循调用约定、将寄存器保存在堆栈...这一切似乎很快变得非常混乱和难以承受,我迷失了方向!
至少在概念上,我不难找出解决特定问题的算法。它更多地与项目的大局、整体结构和设计有关。
鉴于此,您能否指出一种模式,提供一些技巧或最佳实践,以在实际编写代码之前对所有内容进行排序,以便我不会在这个过程中迷失自己?
问题是将可移植可执行映像加载到随机地址。
我们以kernel32.dll为例,加载于0x75A00000。
我可以看到在图像的偏移 0x10e15 处有一条汇编指令,这取决于图像所在的位置。
地址:75A10E13 字节:8B 35 18 03 AE 75 命令:MOV ESI,DWORD PTR DS:[75AE0318]
事实证明,通过启动可执行文件,我们必须告诉系统我们需要重定位到这个地址。
系统查看可执行文件中的重定位表,并看到以下内容: 基本重定位表
为了获取要移动的第一个元素的绝对地址,我执行以下操作:将虚拟地址添加到图像的地址,然后将块的第一个元素添加到结果数字。
0x75A00000 + 0x10000 + 0x3E15 = 75A10E15
这是一个很好的数字,但总是比我预期多 0x3000。我只需减去 0x3000 就可以了。请帮我找到答案,x86 的 0x3000 从哪里来?
看起来JavaScript的number类型与C和C++的double类型完全相同,并且都是IEEE 754-1985。
JavaScript 可以使用 IEEE 754 作为整数,但是当数字变大或进行算术计算(例如除以10或 by )时3,它似乎可以切换到浮点模式。现在,C 和 C++ 仅使用 IEEE 754 作为double,因此仅使用浮点部分,而不使用“整数”部分。因此,C 和 C++ 是否未使用整数表示形式?
(C 未使用NaN, Infinite, -Infinite,-0因为我记得在 C 中从未使用过它们)。
作为一个新手,我正在遵循教程。一种是在 VS 2022 的内联汇编中将字符串中的所有字符大写:
int main()
{
char mystr[] = "Hello World:";
_asm
{
mov ecx, length mystr
my: cmp [mystr + ecx], 'a';
jl nocap;
cmp [mystr + ecx], 'z';
ja nocap;
sub [mystr + ecx], 32;
nocap:
loop my
}
std::cout << mystr;
Run Code Online (Sandbox Code Playgroud)
我的问题是:为什么这个程序集不需要节,例如 .data、.text 或 _start:示例中可能混合了 x86 asm 和 Linux asm。
我觉得这个问题可能有点蠢。。
由于我们存储位来指示数字,并且由于我们拥有整个 RAM,因此我们应该能够拥有一个无限大小(实际上是自定义大小)的数字,该数字可以占用整个 RAM(或其指定部分) )。
正确的?
例如,如果我们这样做:
mov ax, 0xFFFF
add ax, 1
jc custom_function ; if I remember correctly jc checks the carry flag
Run Code Online (Sandbox Code Playgroud)
custom_function 是一个标签/函数,它具有一种算法来设置下一个位以创建无限大小的数字。
问题
这可能吗?如果不是无限大小的数字,则指定自定义(比默认值更长或更短)
我怀疑,如果可能的话,它的性能会很差(即使数量更短)。你怎么认为?
你认为拥有这样的东西会很好吗?(也许在内存有限的旧系统或嵌入式系统中这会更有效?)