📄 preparing-asm_4.htm
字号:
-4(%ebp) # cr0 =
5
<BR> movl -4(%ebp),
%eax # %eax =
cr0<BR>#APP
<BR> movl %eax,
%cr0
<BR>#NO_APP
<BR> movl $0,
%eax
<BR>
leave
<BR>
ret
<BR></P>
<P>我们从编译出的汇编代码可以看到,在"Instruction List"之前,GCC按照我们的输入约束"a",将变量cr0的内容装入了eax寄存器。</P>
<P><FONT face="Times New Roman CE" size=4><STRONG>3. Operation
Constraint</STRONG></FONT></P>
<P>每一个Input和Output表达式都必须指定自己的操作约束Operation
Constraint,我们这里来讨论在80386平台上所可能使用的操作约束。</P>
<P>1、寄存器约束</P>
<P>当你当前的输入或输入需要借助一个寄存器时,你需要为其指定一个寄存器约束。你可以直接指定一个寄存器的名字,比如:</P>
<P>__asm__ __volatile__("movl %0, %%cr0"::"eax" (cr0));</P>
<P>也可以指定一个缩写,比如:</P>
<P>__asm__ __volatile__("movl %0, %%cr0"::"a" (cr0));</P>
<P>如果你指定一个缩写,比如字母a,则GCC将会根据当前操作表达式中C/C++表达式的宽度决定使用%eax,还是%ax或%al。比如:</P>
<P>unsigned short __shrt;</P>
<P>__asm__ ("mov %0,%%bx" : : "a"(__shrt));</P>
<P>由于变量__shrt是16-bit short类型,则编译出来的汇编代码中,则会让此变量使用%ex寄存器。编译结果为:</P>
<P> movw -2(%ebp),
%ax # %ax = __shrt<BR>#APP<BR>
movl %ax, %bx<BR>#NO_APP</P>
<P>无论是Input,还是Output操作表达式约束,都可以使用寄存器约束。</P>
<P>下表中列出了常用的寄存器约束的缩写。</P>
<P>
<TABLE cellSpacing=0 cellPadding=0 width="100%" border=1>
<TBODY>
<TR>
<TD><STRONG><FONT face=宋体>约束</FONT></STRONG></TD>
<TD>Input/Output</TD>
<TD><STRONG><FONT face=宋体>意义</FONT></STRONG></TD></TR>
<TR>
<TD>r</TD>
<TD>I,O</TD>
<TD>表示使用一个通用寄存器,由GCC在%eax/%ax/%al, %ebx/%bx/%bl, %ecx/%cx/%cl,
%edx/%dx/%dl中选取一个GCC认为合适的。</TD></TR>
<TR>
<TD>q</TD>
<TD>I,O</TD>
<TD>表示使用一个通用寄存器,和r的意义相同。</TD></TR>
<TR>
<TD>a</TD>
<TD>I,O</TD>
<TD>表示使用%eax / %ax / %al</TD></TR>
<TR>
<TD>b</TD>
<TD>I,O</TD>
<TD>表示使用%ebx / %bx / %bl</TD></TR>
<TR>
<TD>c</TD>
<TD>I,O</TD>
<TD>表示使用%ecx / %cx / %cl</TD></TR>
<TR>
<TD>d</TD>
<TD>I,O</TD>
<TD>表示使用%edx / %dx / %dl</TD></TR>
<TR>
<TD>D</TD>
<TD>I,O</TD>
<TD>表示使用%edi / %di</TD></TR>
<TR>
<TD>S</TD>
<TD>I,O</TD>
<TD>表示使用%esi / %si</TD></TR>
<TR>
<TD>f</TD>
<TD>I,O</TD>
<TD>表示使用浮点寄存器</TD></TR>
<TR>
<TD>t</TD>
<TD>I,O</TD>
<TD>表示使用第一个浮点寄存器</TD></TR>
<TR>
<TD>u</TD>
<TD>I,O</TD>
<TD>表示使用第二个浮点寄存器</TD></TR></TBODY></TABLE></P>
<DT>
<DT>2、内存约束
<P>如果一个Input/Output操作表达式的C/C++表达式表现为一个内存地址,不想借助于任何寄存器,则可以使用内存约束。比如:</P>
<P>__asm__ ("lidt %0" : "=m"(__idt_addr)); 或 __asm__ ("lidt %0" :
:"m"(__idt_addr));</P>
<P>我们看一下它们分别被放在一个C源文件中,然后被GCC编译后的结果:</P>
<P>$ cat example5.c</P>
<P>// 本例中,变量sh被作为一个内存输入</P>
<P>int main(int __argc, char*
__argv[])
<BR>{
<BR> char* sh =
(char*)&__argc;
<BR>
<BR> __asm__ __volatile__("lidt %0" :
: "m" (sh));
<BR>
<BR> return
0;
<BR>} </P>
<P>$ gcc -S example5.c</P>
<P>$ cat example5.s</P>
<P>main:
<BR> pushl
%ebp
<BR> movl %esp,
%ebp <BR>
subl $4, %esp
<BR> leal
8(%ebp), %eax <BR>
movl %eax, -4(%ebp) # sh = (char*)
&__argc<BR>#APP
<BR> lidt
-4(%ebp)
<BR>#NO_APP
<BR> movl $0,
%eax
<BR>
leave
<BR>
ret
<BR></P>
<P>$ cat example6.c</P>
<P>// 本例中,变量sh被作为一个内存输出</P>
<P>int main(int __argc, char*
__argv[])
<BR>{
<BR> char* sh =
(char*)&__argc;
<BR>
<BR> __asm__ __volatile__("lidt %0" :
"=m" (sh));
<BR>
<BR> return
0;
<BR>} </P>
<P>$ gcc -S example6.c</P>
<P>$ cat example6.s</P>
<P>main:<BR> pushl
%ebp<BR> movl &n
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -