?简单的介绍?关键字? __asm__: 必需; __volatile__: 不是必需的吗?格式? __asm__ __volatile __(“指令列表”: 输出: 输入: 破坏/修改); •除了上述四个部分可以默认设置之外,当后三个部分不可用时,它将简化为基本的装配,否则为GCC装配?每个操作数的含义是什么?指令列表: 所有内联操作定义?输出: 所有输出变量?输入: 所有输入变量?破坏/修改: 可以修改的语句?每个操作数的集合?指令列表: 各种intel和AT&T组装操作命令?输出: 输出操作数的变量名称以及使用的模式和寄存器/存储器?输入: 输入操作数的变量名以及使用的模式和寄存器/存储器?破坏/修改: 关于寄存器或内存可能更改的提醒声明?句法?注册参考?例如,%Eax,%ebx?操作数的顺序?对,例如“ Movl%eax(源操作数),%ebx(目标操作数)”?立即数据?在$之前c语言对应汇编语句,例如. “ Movl $ 0x0 4,%ebx”或para = 0x04 movl $ para,%ebx,立即将04h加载到寄存器ebx中?符号常量(直接参考)?例如,值: .long0x12a3f2de movl值,%ebx(将常量0x12a3f2dez加载到寄存器ebx)?例如“ movl $ value,%ebx”(将值的地址加载到寄存器ebx中)?操作数的长度?指令最后一个符号的含义: b,w,l分别是: 字节,word,long,如果未指定操作数的长度,则根据目标操作数的长度进行设置?符号扩展和零扩展指令(AT&T和Intel汇编指令的不同部分)?需要指定源和目标操作数的长度?AT&T格式: movs(符号扩展名)和movz(零扩展名)?英特尔格式: movsx(符号扩展名)和movzx(零扩展名)?例如,Movsbl表示movs( from()字节(to)long; movsbl%al,%edx(类似于Intel)?例如,movsbw表示movs(from)字节(to)字movsbw%al,%dx(类似于Intel)?其他是: cbw,cwde,cwd,cdq等(英特尔),cbtw,cwtl,cwtd,cltd等(AT和T)?并跳转说明?节内调用和跳转: 调用,退出,跳转?交叉呼叫和跳转: lcall,lret,ljmp?段间调用和跳转指令格式: “ lcall / ljmp $ section,$ offset”?段间返回命令是: “ lret $ stack-adjust”?字首?字符串重复操作(rep,repne)?指定操作段(cs,ds,ss,es,fs,gs)?执行总线束缚(锁定)?指定操作的地址和大小(data16,addr16)?在AT&T汇编语法中,前缀通常放在单行上,后没有操作数. 例如,对于重复的scas指令,其写法是: repnescas?操作该代码的含义和用法: ?在AT&T语法中,您只需要根据以下部分的格式指定相应的部分前缀: memory-operand Eg.lcall%cs: realmode_switch? “锁定”是为了确保在执行指令期间禁止所有中断,它对指令起作用: ADD,ADC等. 内存参考? Intel语法的间接内存参考格式为: 节: [基数+索引*比例+位移]? AT&T语法中的相应形式是: section: 位移(基数,dex,比例)?基址和索引是任意的32位基址和索引寄存器吗?比例值是: 1、2、4、8,默认值为1?段可以指定任何寄存器作为段前缀,默认段的寄存器在不同情况下会有所不同(如果指令中指定了默认段前缀,编译器将不会在目标代码中生成此段前缀代码)?例如-4(%ebp): base =%ebp,位移= -4,未指定部分,因为base =%ebp,因此默认部分=%ss,index,scale未指定,则index为0?有关其他说明,请参阅“ c和汇编混合语法” GCC内联汇编?基本的内联汇编(仅指令列表,无输入/输出/障碍)?例如.__ asm __(“ move%esp,%eax”);?例如.__ asm__(“ mov $ 1,%eax xor%ebx,%ebx int $ 0 x80”);?例如. __asm __(“ movl $ 1,%eax \ r \ t”“ xor%ebx,%ebx \ r \ t”“ int $ 0x80”);?基本格式: __asm__ __volatile __(“指令列表”); __asm__: 是GCC关键字asm的宏定义,它是每个内联汇编表达式的开始,是否必要Less?指令列表: 是一系列汇编指令,可以为空?可以将所有指令放在一个引号中吗?每次执行都可以放在一行上吗?多个指令放在一行上,由分号或换行符分隔开(大多数情况下加\ t)?也可以放在多个引号中吗?除最后一对引号外,所有先前的引号必须在最后一条指令后带有分号或\ n或\ t. 原则摘要: 任意两条指令要么用分号分隔,要么放在两行上(您可以放它,也可以加\ n)? __Volatile__: 内联关键字volatile的GCC宏定义,您不能使用它,用过的指令保留每条指令(在优化过程中不会省略)?用C / C ++表达式内联汇编?基本格式: __asm__ __volatile __(“指令列表”: 输出: 输入: clobber);?基本规则: ?如果缓冲区为空,必须省略前面的冒号吗?如果指令列表为空,则输入,输出,缓冲区是否可以为空?如果输出,则输入,破坏者都为空. 输出和输入之前的冒号可以忽略也可以忽略(所有省略都减少为基本的内联汇编). C在嵌入式汇编中,指令列表中的寄存器前面需要两个百分号吗?输入,输入是否为空,输出是否不为空,输入前的冒号可以省略/不省略?后面不是空的,前面是空的,那么前面的结肠必须保留吗?指令列表-> C内联汇编之后是否有冒号?输出?例如. __Asm __(“%%cr0,%0”: “ = a”(cr0));?输出部分是: “ = a”(rc0),这是一个指定输出操作的操作表达式? (cr0): C / C ++表达式,用于保存内联汇编的输出值,其运算等于C / C ++的等效赋值rc0 = output_value,也就是说,它只能是可以合法地放在C / C ++中赋值运算=表达式在左侧? “ = A”(称为“操作约束”)包含两个约束: 等号=和字母a,其中等号=表示括号中的左值表达式cr0是只写的,只能由当前值输入内联汇编,并且可以用作输出. 字母a是寄存器eax,ax,al的缩写,表示应从eax寄存器中获取cr0的值,即cro = eax,汇编指令为: movl%eax,address_of_cr0?关于“ =”,等号(=)表示当前表达式是只写的. 如果是加号(+),则表示当前表达式是可读写的. 如果它是默认值(),则表示当前表达式是只读的. 被逗号隔开?输入?例如. __Asm __(“ mov %%,%% db7” ::“ a”(cpu-> db7))? “ A”(cpu-> db7): 变成“输入表达式”,而“ a”和(cpu-> db7)这两个部分是必不可少的吗?cpu-> db7是C / C ++表达式,不一定是左值,它也可以是右边的表达式吗?用引号引起来是约束部分. 与输出表达式不同,它不允许指定加号和等号约束. 默认为只读. 您需要指定一个寄存器约束. A表示通过寄存器eax?操作约束?寄存器约束?将输入变量输入到内联汇编中R: 表示通用寄存器,由GCC控制,形式为%eax%ax%al,%eb x%bx %bl,%ecx%cx%cl,%edx%dx%dl选择合适的GCC吗?q: 代表通用寄存器,其含义与r相同a: 代表使用%eax%ax %al?b: 使用%ebx%bx%bl?c: 使用%ecx%cx%cl?d: 使用%edx%dx%dl?s: 使用%esi%si?f: 使用浮点寄存器t : 表示使用第一个浮点寄存器?u: 表示t o使用第二个浮点寄存器?内存限制?例如.__ asm __(“ lidt%0”: “ = m”(__ idt_addr));导出时c语言对应汇编语句,GCC不会根据该语句进行任何输入和输出处理,因为它不依赖寄存器,而是直接使用它? M: 是指系统支持的任何存储方法,而无需使用寄存器?立即数量限制?例如.__ asm__ __volatile __(“ moval%0,%% eax” ::“ i”(100));? I / I: 表示输入表达式是立即数(整数),而不需要任何寄存器? f / F: 表示输入表达式是一个立即数(浮点数),不需要任何寄存器吗?一般约束? g: 表示它可以使用通用寄存器,内存,立即数据和任何其他处理方法? 0,1,2,3 ...: 表示将相同的寄存器/存储器用作第n个操作数?具有C / C ++表达式的内联程序集,操作表达式按列出的顺序编号,最多允许10个操作表达式?如果输入操作表达式将0-9中的数字用作其约束,则相当于要GCC声明“我要使用与输出操作表达式具有数字1相同的寄存器或内存地址”?修饰符?等号(=)和加号(+)用于修改输出运算表达式. 符号(&)仅可用于输出运算表达式的修改,指出“没有输入运算表达式应分配与此输出运算表达式相同的寄存器”表示输出运算表达式在所有输入运算表达式之前输出是输入,不包括使用输出是否已预先使用输入?百分号(%): 仅在输入操作表达式中声明“当前输入操作表达式中的C / C ++表达式可以是下一个输入”在操作表达式中的C / C ++表达式互换”,通常用于符号交换法运算?修饰语是什么意思?= / + /&: 输出只写/读写/互斥?%: 输入可互换?占位符?%0,%1,等等,每个占位符将被替换使用在编译时由相应的输入/输出操作表达式指定的寄存器/内存地址/立即数?必须使用占位符: ?输入指定内存地址(“ m”),该地址不能预先确定,仅可以使用一个占位符吗?在输出中使用通用寄存器(“ = r”),所以我不知道使用了哪个占位符,只能使用占位符吗?Clobber(通知GCC当前语句可以修改某些寄存器或内存,希望在编译时将其考虑在内,然后ou可以声明这些内容吗?发生一般情况: 寄存器出现在“指令列表”中,但未由输入/输出指定,当输入/输出使用“ r” /“ g”时,GCC也未选择该寄存器,并且该寄存器由中的指令修改“指令列表”,并且应该发送内存仅在当前的内联汇编中使用?如果在内联汇编语句的clobber字段中向GCC声明了寄存器的内容,则在编译GCC时,如果在此内联汇编语句之后找到了声明的寄存器内容. 如果您继续使用它,则该寄存器的内容将首先保存,然后在内联Assembly语句后恢复内容.
?如果寄存器在Clobber中声明,那么它不能再用于输入/输出?修改内存: 如果将内存的内容读入寄存器,则使用“内存”声明内存可能会更改,然后,在执行内联汇编后,如果仍然需要此内存的内容,则使用寄存器将不会直接给出,但是读取的内存将被重新读取?使用“ cc”: 当内联指令包含eflags寄存器的效果时,最好在使用条件标志时添加此语句,因为条件标志可能会在内联汇编中更改? 0-9: 用于声明n个输入/输出操作表达式的寄存器已更改
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-169626-1.html