我一直在研究一个(C++)项目,它需要完全动态分配的函数,这意味着malloc/new和mprotect,然后手动修改缓冲区到汇编代码.因此我完全想知道,我的这个"缓冲区"需要什么,因为它是任何其他_cdecl函数的复制品.例如:
int ImAcDeclFunc(int a, int b)
{
return a + b;
}
Run Code Online (Sandbox Code Playgroud)
如果我想从字面上创建这个函数的副本,但是完全动态,那需要什么(并记住它是带有内联汇编的C++ )?对于初学者,我想我必须做这样的事情(或类似的解决方案):
// My main....
byte * ImAcDeclFunc = new byte[memory];
mprotect(Align(ImAcDeclFunc), pageSize, PROT_EXEC | PROT_READ | PROT_WRITE);
Run Code Online (Sandbox Code Playgroud)
在此之后我将不得不找出汇编代码ImAcDeclFunc(int a, int b);.现在我在组装时仍然很糟糕,那么这个函数将如何用于AT&T语法?这是我的大胆尝试:
push %ebp
movl %%ebp, %%esp
movl 8(%ebp), %%eax
movl 12(%ebp), %%edx
addl edx, eax
pop ebp
ret
Run Code Online (Sandbox Code Playgroud)
现在如果这段代码是正确的(我非常怀疑,请纠正我)我只需要在十六进制中找到这个代码的值(例如,'jmp'是0xE9而'inc'是0xFE),并直接使用这些值C++?如果我继续以前的C++代码:
*ImAcDeclFunc = 'hex value for push'; // This is 'push' from the first line
*(uint)(ImAcDeclFunc + 1) = 'address to …Run Code Online (Sandbox Code Playgroud) C++
ATT大会
我试图理解以下两条指令的行为:
pushl %esp
Run Code Online (Sandbox Code Playgroud)
和:
popl %esp
Run Code Online (Sandbox Code Playgroud)
请注意,它们将计算出的值存储回来%esp.
我正在独立地考虑这些指令,而不是按顺序.我知道存储的值%esp总是递增/递减之前的值,但是我怎么能用汇编语言表示行为呢?这是我到目前为止所提出的:
推送:
movl %esp, %edx 1. save value of %esp
subl $4, %esp 2. decrement stack pointer
movl %edx, (%esp) 3. store old value of %esp on top of stack
Run Code Online (Sandbox Code Playgroud)
对于pop:
movl (%esp), %esp You wouldn’t need the increment portion.
Run Code Online (Sandbox Code Playgroud)
它是否正确?如果没有,我哪里错了?谢谢.
英特尔和AT&T语法中内存寻址的一般形式如下:
[base + index*scale + disp]
disp(base, index, scale)
Run Code Online (Sandbox Code Playgroud)
我的问题如下:
base和index任意注册?scale采用什么值,是1,2,4和8(默认值为1)?index和disp可互换的(唯一的区别index是寄存器disp是一个常数)?我正在读我的教科书,它有交换功能的代码:
在C:
int exchange(int *xp, int y) {
int x = *xp;
*xp = y;
return x;
}
Run Code Online (Sandbox Code Playgroud)
在x86带注释的程序集中:
// xp is at %ebp + 8, y at %ebp + 12
movl 8(%ebp), %edx // get xp
movl (%edx), %eax // get x at xp
movl 12(%ebp), %ecx // get y
movl %ecx, (%edx) // store y at xp
Run Code Online (Sandbox Code Playgroud)
因此,根据我的理解,如果int*xp指向地址A处的int I,则汇编代码的第一行将A存储在%edx处.然后在第二行中取消引用并存储在%eax中.
如果这是真的,我想知道为什么第1行的"8(%ebp)"没有取消引用指针,将int存储在%edx而不是地址A中?这不是括号在汇编中做的吗?
或者这是否意味着当指针被推入堆栈时,指针的地址被推上而不是它所持有的值,因此8(%ebp)技术上持有&xp?
只是想澄清我的理解是否正确.
我正在研究linux内核源码(旧版本0.11v).当我检查fork系统调用时,有一些asm代码用于上下文切换,如下所示:
/*
* switch_to(n) should switch tasks to task nr n, first
* checking that n isn't the current task, in which case it does nothing.
* This also clears the TS-flag if the task we switched to has used
* tha math co-processor latest.
*/
#define switch_to(n) {\
struct {long a,b;} __tmp; \
__asm__("cmpl %%ecx,current\n\t" \
"je 1f\n\t" \
"movw %%dx,%1\n\t" \
"xchgl %%ecx,current\n\t" \
"ljmp *%0\n\t" \
"cmpl %%ecx,last_task_used_math\n\t" \
"jne 1f\n\t" \
"clts\n" \
"1:" \
::"m" …Run Code Online (Sandbox Code Playgroud) 在GNU as(GNU汇编程序)中,以下代码无错误地汇编:
mov $(80 * 24 + 4), %cx
Run Code Online (Sandbox Code Playgroud)
但是,此代码不会:
mov $(80 * 24 / 4), %cx
Run Code Online (Sandbox Code Playgroud)
发出非常意外的错误:
example.S: Assembler messages:
example.S:42: Error: unbalanced parenthesis in operand 1.
Run Code Online (Sandbox Code Playgroud)
唯一的区别是后者使用除法而不是加法.根据手册,这应该是有效的.
($<expression>将一个立即嵌入到已组合的输出中;即一个常量.算术在"编译时"执行.我可以计算出数学,但它在扩展形式中更有意义.)
我最近开始寻求更好地理解我的计算机是如何工作的.我的问题是关于push和pushq之间的区别.
我知道push会将一个值写入堆栈,我的假设是pushq做了类似的事情.q在那里的事实让我觉得应该有一个微妙的区别,但我似乎无法理解差异.
我说在使用命令'layout asm'使用gdb调试文件/ lib/udev/iphone-set-info时考虑这个问题.
有问题的代码是:
pushq $0x0
push %r9
Run Code Online (Sandbox Code Playgroud)
我知道$ 0x0对于NULL是十六进制的,而%r9是通用寄存器之一.这只是意味着Null我们写入堆栈,其上面写有寄存器%r9吗?
一直通过AT&T语法关注youtube上的汇编教程。我刚刚学习了使用.type指令声明(如果在这里是正确的术语)函数,例如:
.type MyFunction, @function
Run Code Online (Sandbox Code Playgroud)
现在,我可以像下面这样定义我的函数:
MyFunction:
<code here>
Run Code Online (Sandbox Code Playgroud)
然后在任何时候调用它:
call MyFunction
Run Code Online (Sandbox Code Playgroud)
我知道在教程之前,我们只是在创建一个附加到一些代码的标签:
MyLabel:
<code here>
Run Code Online (Sandbox Code Playgroud)
然后可以这样称呼它:
call MyLabel
Run Code Online (Sandbox Code Playgroud)
所以我的问题是:
用.type声明的函数和仅用标签声明的'function'到底有什么区别?什么时候应该使用另一个,或者这有关系吗?
最近,我读了一些关于计算机科学的书。我编写了一些 C 代码,并使用gcc和objdump反汇编了它们。
以下C代码:
#include <stdio.h>
#include <stdbool.h>
int dojob()
{
static short num[ ][4] = { {2, 9, -1, 5}, {3, 8, 2, -6}};
static short *pn[ ] = {num[0], num[1]};
static short s[2] = {0, 0};
int i, j;
for (i=0; i<2; i++) {
for (j=0; j<4; j++){
s[i] += *pn[i]++;
}
printf ("sum of line %d: %d\n", i+1, s[i]);
}
return 0;
}
int main ( )
{
dojob();
}
Run Code Online (Sandbox Code Playgroud)
得到以下汇编代码(AT&T 语法;只有函数dojob …