b2科目四模拟试题多少题驾考考爆了怎么补救
b2科目四模拟试题多少题 驾考考爆了怎么补救

嵌套的C语言汇编语言

电脑杂谈  发布时间:2020-05-02 01:04:17  来源:网络整理

c语言对应汇编语句_c语言与汇编语言的区别_汇编语言和c语言哪个难

在中使用内联汇编

在Visual C ++中使用内联汇编使用内联汇编将汇编语言指令嵌入C / C ++代码中,而无需其他汇编和连接步骤. 在Visual C ++中,内联汇编是一个内置的编译器,因此不需要配置单独的汇编工具(例如MASM). 在这里,我们将以Visual Studio .NET 2003为背景,介绍在Visual C ++中使用内联汇编的相关知识(如果是早期版本,可能会有一些差异). 内联汇编代码可以使用C / C ++变量和函数,因此可以轻松地集成到C / C ++代码中. 仅使用C / C ++即可完成非常繁琐或无法完成的任务. 1.优点使用内联汇编可以将汇编语言指令嵌入C / C ++代码中,而无需其他汇编和链接步骤. 在Visual C ++中,内联汇编是一个内置的编译器,因此不需要配置单独的汇编工具(例如MASM). 在这里,我们将以Visual Studio .NET 2003为背景,介绍在Visual C ++中使用内联汇编的相关知识(如果是早期版本,则可能存在一些不一致之处). 内联汇编代码可以使用C / C ++变量和函数,因此可以轻松地集成到C / C ++代码中.

仅使用C / C ++即可完成非常繁琐或无法完成的任务. 内联汇编的用途包括: 用汇编语言编写特定功能;编写非常高速的代码;直接访问设备驱动程序中的硬件;为裸函数编写初始化和结束代码. 其次,关键字使用内联汇编来使用__asm关键字,该关键字可以出现在允许C / C ++语句的任何位置. 让我们看一些示例: 简单的__asm块: __asm {MOV AL,2 MOV DX,0xD007 OUT AL,DX}在每个汇编指令之前添加__asm关键字: __asm MOV AL,2__asm MOV DX ,0xD007 __asm OUT AL,DX因为__asm关键字是语句分隔符,所以您可以在同一行上放置多个汇编指令: __asm MOV AL,2 __asm MOV DX,0xD007 __asm OUT AL ,DX显然,第一种方法与C / C ++相同,样式非常一致,并且汇编代码和C / C ++代码明确分开,避免了__asm关键字的重复输入,所以推荐第一种方法. 与C / C ++中的“ {}”不同,__asm块的“ {}”不会影响C / C ++变量的范围.

汇编语言和c语言哪个难_c语言对应汇编语句_c语言与汇编语言的区别

同时,可以嵌套__asm块,并且嵌套不会影响变量的范围. 为了与Visual C ++的早期版本兼容,_asm和__asm具有相同的含义. 此外,Visual C ++支持标准的C ++ asm关键字,但是它不生成任何指令,并且其作用仅限于没有编译错误的编译器. 要使用内联汇编,必须使用__asm而不是asm关键字. 3.汇编语言1.指令集嵌入式汇编支持Intel Pentium 4和AMD Athlon的所有指令. 可以使用_EMIT伪指令创建来自其他处理器的更多指令(请参见下面的_EMIT伪指令的说明). 2. MASM表达式在内联汇编代码中,可以使用所有MASM表达式(MASM表达式是指用于计算值或地址的运算符和操作数的组合). 3.数据指示符和运算符尽管__asm块中允许使用C / C ++数据类型和对象,但它不能使用MASM指示符和运算符来定义数据对象. 这里特别指出,__ asm块中不允许MASM中的定义指示符(DB,DW,DD,DQ,DT和DF),并且不允许DUP和THIS运算符.

MASM中的结构和记录不再有效. 内联汇编不接受STRUC,RECORD,WIDTH或MASK. 4. EVEN和ALIGN指示器尽管内联汇编不支持大多数MASM指示器,但它支持EVEN和ALIGN. 必要时,这些指示器将NOP指令(无操作)添加到汇编代码中,以使标签与特定边界对齐. 这可以使某些处理器更高效地提取指令. 5. MASM宏指示器内联程序集不是宏程序集. 不能使用MASM宏指示符(MACRO,REPT,IRC,IRP和ENDM)和宏运算符(<>,!,&,%和And.TYPE). 6.段必须使用寄存器而不是名称来指示段(段名称“ _TEXT”无效). 另,例如ES: [EBX]. 7.类型和变量大小在内联汇编中,可以使用LENGTH,SIZE和TYPE来获取C / C ++变量和类型的大小. * LENGTH运算符用于获取C / C ++中数组中的元素数(如果不是数组,则结果为1). * SIZE运算符可以获得C / C ++变量的大小(变量的大小是LENGTH和TYPE的乘积).

* TYPE运算符可以返回C / C ++类型和变量的大小(如果变量是数组,它将获得数组中单个元素的大小). 例如,在程序中定义了一个8维整数变量: int iArray [8];以下是从C和汇编表达式获得的iArray及其元素的相关值: __asm长度iArray大小iArray TYPE iArray 8.注释内联可以在汇编过程中使用汇编语言的注释,即“;”. 例如: __asm MOV EAX,OFFSET pbBuff; pbBuff的加载地址因为C / C ++宏将扩展为逻辑行,所以为了避免由于在宏中使用汇编语言注释而引起的混乱,内联汇编还允许使用C / C ++样式笔记. 9. _EMIT伪指令_EMIT伪指令与MASM中的DB等效,但是_EMIT一次只能在当前代码段(.text段)中定义一个字节. 例如: __asm {JMP _CodeLabel C sizeof(iArray)/ sizeof(iArray [0])sizeof(iArray)sizeof(iArray [0])8 32 4 Size_EMIT 0x00 _EMIT 0x01;定义混合在代码段_CodeLabel中的数据: _EMIT 0x90} 10.寄存器用法;这是代码; NOP指令通常不能假定__asm块开头的寄存器具有已知值.

c语言对应汇编语句_汇编语言和c语言哪个难_c语言与汇编语言的区别

不能保证寄存器的值从__asm块保留到另一个__asm块. 如果将一个函数声明为__fastcall,则其参数将通过寄存器而不是堆栈传递. 这将导致__asm块出现问题,因为无法告知函数哪个参数在哪个寄存器中. 如果该函数在EAX中接收到参数并立即在EAX中存储一个值,则原始参数将丢失. 此外,在所有声明为__fastcall的函数中,必须始终保留ECX寄存器. 为避免上述冲突,不应将包含__asm块的函数声明为__fastcall调用方法. 提示: 如果使用EAX,EBX,ECX,EDX,ESI和EDI寄存器,则无需保存. 但是,如果使用DS,SS,SP,BP和标志寄存器,则应使用PUSH保存这些寄存器. 提示: 如果在程序中更改了STD和CLD的方向标志,则必须将其恢复为原始值. 4.使用C / C ++元素1.可用的C / C ++元素可以混合使用C / C ++和汇编语言,可以内联使用C / C ++变量和许多其他C / C ++元素汇编,包括: 符号,包括Label,变量和函数名;常量,包括符号常量和枚举成员;宏定义和预处理指标;注释,包括“ / ** /”和“ //”;类型名称,包括MASM类型中的所有合法名称; typedef名称,通常使用PTR和TYPE运算符,或使用指定的结构或枚举成员.

0x100和100H是内联汇编,可以使用C / C ++或汇编语言的基数计数方法. 例如,相等. 2.运算符的使用C / C ++运算符,例如“ <<”,不能用于内联汇编. 但是,对于C / C ++和MASM通用的运算符(例如“ *”和“ []”运算符)都被视为汇编语言运算符,并且可以使用. 例如: int iArray [10]; __asm MOV iArray [6],BX iArray [6] = 0 ;;将BX存储在iArray + 6(未缩放)//将0存储在iArray + 12(缩放)在内联汇编中,可以使用TYPE运算符使其与C / C ++一致. 例如,以下两个语句是相同的: __asm MOV iArray [6 * TYPE int],0 iArray [6] = 0; 3. __asm块中使用的C / C ++符号可以引用范围C ++符号中的所有C / C,包括变量名,函数名和标签. 但是c语言对应汇编语句,您不能访问C ++类的成员函数.

以下是在嵌入式汇编中使用C / C ++符号的一些限制: 每个汇编语句只能包含一个C / C ++符号. 在单个汇编指令中,多个符号只能出现在LENGTH,TYPE或SIZE表达式中. __asm块中引用的函数必须首先声明. 否则,编译器将无法区分__asm块中的函数名称和标签. __asm块中不能使用MASM保留字的C / C ++符号(不区分大小写). MASM保留字包括指令名称(例如PUSH)和寄存器名称(例如ESI). __asm块中无法识别结构和联合标签. 4.在C / C ++中访问数据内联汇编的一大便利是它可以按名称引用C / C ++变量. 例如,如果C / C ++变量iVar在范围内: __asm MOV EAX,iVar;如果C / C ++中的类,结构或枚举成员具有唯一的名称,则在__asm块中将iVar的值存储在EAX中. 只能由成员名称访问(省略变量名称或typedef名称)在“. ”运算符之前). 但是,如果成员不是唯一的,则必须在“. ”之前添加变量名称或typedef名称. 运算符.

c语言对应汇编语句_汇编语言和c语言哪个难_c语言与汇编语言的区别

例如,以下两个结构具有成员变量SameName: struct FIRST_TYPE {char * pszWeasel; int SameName;}; struct SECOND_TYPE {int iWonton ;;将0存储在iArray + 12 // //将0存储在iArray + 12long SameName;};如果您按以下方式声明变量: struct FIRST_TYPE ftTest; struct SECOND_TYPE stTemp;然后,所有对SameName成员的引用都必须使用变量名,因为SameName不是唯一的. 另外,由于上面的pszWeasel变量具有唯一的名称,因此您只能使用其成员名称来引用它: __asm {MOV EBX,OFFSET ftTest MOV ECX,[EBX] ftTest.SameName MOV ESI,[EBX]. PszWeasel}: 省略变量名只是为了方便编写代码,生成的汇编指令是相同的. 5.使用内联汇编编写函数如果使用内联汇编编写函数,则很容易传递参数并返回值.

看下面的例子,比较以独立汇编和内联汇编编写的功能: PowerAsm.asm;计算整数PUBLIC _TEXT GetPowerAsm段字PUBLIC'CODE'的幂;必须使用“ ftTest”;可以省略“ ftTest” GetPowerAsm PROC PUSH MOV EBP EBP,ESP;保存EBP;将ESP移入EBP,以便我们可以参考;到堆栈上的参数MOV MOV SHL POP EAX,[EBP + 4] ECX,[EBP + 6] EAX,CL EBP;得到第一个论点;得到第二个论点; EAX = EAX *(2 ^ CL);恢复EBPRET GetPowerAsm ENDP _TEXT ENDS END;在EAXC / C ++函数中,以sum返回的函数通常使用堆栈来传递参数,因此上述函数需要传递堆栈位置来访问其参数(在MASM或某些其他汇编工具中,也可以访问堆栈参数和本地按名称堆叠变量. )

以下程序是使用内联汇编编写的: // PowerC.c #include int GetPowerC(int iNum,int iPower); int main(){printf(“ 3乘以2等于5的幂是%d \ n”,GetPowerC(3,5));} int GetPowerC(int iNum,int iPower){__asm {MOV EAX,iNum 获得第一个论点MOV ECX,iPower;获取第二个参数SHL EAX,CL} //在EAX中返回结果}内联汇编中编写的GetPowerC函数可以通过参数名称引用其参数. 由于GetPowerC函数不执行C return语句,因此编译器将给出警告消息. 我们可以通过#pragma warning禁用此警告的生成. 内联汇编的用途之一是为裸函数编写初始化代码和结束代码.

汇编语言和c语言哪个难_c语言对应汇编语句_c语言与汇编语言的区别

对于常规函数,编译器将自动帮助我们初始化函数(构建参数指针和分配局部变量等)和结束代码(平衡堆栈并返回值等). 使用内联汇编,我们可以自己编写干净的函数. 当然在这个时候; EAX = EAX *(是CL的2的幂),我们必须自己完成一些有关函数初始化和尾部查找的工作. 例如: void __declspec(裸)MyNakedFunction(){//裸函数必须提供自己的序言. __Asm {PUSH EBP MOV ESP,EBP SUB ESP,__ LOCAL_SIZE} //并且我们必须提供结语. __Asm {POP EBP RET}} 6. 调用C / C ++函数内联汇编调用声明为__cdecl(默认值)的C / C ++函数. 调用者必须清除参数堆栈. 以下是调用C / C ++函数的示例: #include char szFormat [] =“%s%s \ n”; char szHello [] =“ Hello”; char szWorld [] =“ world”; void main(){__asm {MOV EAX,OFFSET szWorldPUSH MOV PUSH MOV PUSH CALLEAX EAX,OFFSET szHello EAX EAX,OFFSET szFormat EAX printf //将3个参数压入堆栈. 调用该函数后,调整堆栈ADD}}提示: 参数按从右到左的顺序推入堆栈.

如果调用__stdcall函数,则无需自己清除堆栈. 由于此函数的返回指令为RET n,因此将自动清除堆栈. 大多数Windows API函数都由__stdcall调用(wsprintf等除外). 以下是调用MessageBox函数的示例: #include TCHAR g_tszAppName [] = TEXT(“ API测试”); void main(){TCHAR tszHello [] = TEXT(“ Hello,world!”); __Asm {PUSH PUSH LEA PUSH CALL MB_OK或MB_ICONINFORMATION OFFSET g_tszAppName EAX,tszHello EAX 0 DWORD PTR [MessageBox];注意这不是CALL;全局变量的偏移量;局部变量使用LEA ESP,12MessageBox,但调用重定位的函数地址}}提示: 您可以不受限制地访问C ++成员变量,但不能访问C ++成员函数.

7. 将__asm块定义为C / C ++宏使用C / C ++宏可以轻松地将汇编代码插入源代码中. 但这需要格外注意,因为宏将扩展为逻辑行. 为避免出现问题,请按照以下规则编写宏: 使用花括号将__asm块括起来;在每个汇编指令之前放置__asm关键字;使用经典的C样式注释(“ / * comment * /”),不要使用汇编样式的注释(“; comment”)或单行C / C ++注释(“ // comment”);例如,以下代码定义了一个简单的宏: #define PORTIO __asm //端口输出* / {__asm MOV AL,2 __asm MOV DX,0xD007 __asm OUT DX,AL}乍一看,以下三个__asm关键字似乎是多余的. 实际上,它们是必需的,因为宏将被扩展为一行: __asm / *端口输出* / {__asm MOV AL,2 __asm MOV DX,0xD007 __asm OUT DX,AL} As从扩展代码中可以看出,第三个和第四个__asm关键字是必需的(作为语句分隔符).

在__asm块中,仅__asm关键字和换行符将被视为语句分隔符,并且由于定义为宏的语句块将被视为逻辑行,因此必须在每条指令之前使用它__asm关键字也需要托架. 如果省略它,编译器将不知道汇编代码在哪里结束,并且__asm块后面的C / C ++语句将被视为汇编指令. 同样,由于宏扩展,汇编样式注释(“; comment”)和单行C / C ++注释(“ // commen”)也可能发生错误. 为避免这些错误,在将__asm块定义为宏时使用经典的C样式注释(“ / * comment * /”). 像C / C ++宏一样,以__asm块编写的宏也可以具有参数. 与C / C ++宏不同,__asm宏无法返回值,因此您不能将此宏用作C / C ++表达式. \ \ \ \ \ \ \不要乱叫这种类型的宏. 例如,在声明为__fastcall的函数中调用汇编语言宏可能会导致不可预测的结果(请参见前面的描述). 8.跳转跳转可以使用goto跳转到C / C ++中__asm块中的标签,也可以跳转到__asm块中__asm块中或外部的标签.

__asm块中的标签不区分大小写(命令,指示符等也不区分大小写). 例如: void MyFunction(){goto C_Dest;转到c_dest;转到A_Dest;转到a_dest; __asm {JMP C_Dest;正确的JMP c_dest;错误JMP A_Dest;正确的JMP a_dest;更正a_dest: } C_Dest: 返回;}作为标签,否则它将跳转到要执行的函数,而不是标签. 例如,由于exit是C / C ++的函数,因此以下跳转不会转到exit标签: 错误: 使用函数名称作为标签JNE exit ... exit: ...... / * C / C ++标签* /; __asm标签/ *正确* / / *错误* / / *正确* / / *正确* /美元符号“ $”用于指定当前指令位置,常用于条件跳转,例如: JNE $ + 5 JMP _Label NOP ...... __Label: .....;以下指令的长度为5个字节; $ + 5,跳到此处. 5.在Visual C ++项目中使用独立程序集内联程序集代码不容易移植. 如果您的程序打算在不同类型的机器(例如x86和Alpha)上运行,则可能需要在不同的模块中使用特定的机器代码.

这时,您可以使用MASM(Microsoft宏汇编程序),因为MASM支持更方便的宏和数据指示符. 这里简要介绍了在Visual Studio .NET 2003中调用MASM来编译独立程序集文件的步骤. 在Visual C ++项目中,添加根据MASM要求编写的.asm文件. 在解决方案资源管理器中c语言对应汇编语句,右键单击该文件,选择“属性”菜单项,然后在“属性”对话框中单击“自定义生成步骤”并设置以下各项: 命令行: ML.exe / nologo / c / coff“ -Fo $(IntDir)\ $(InputName).obj“” $(InputPath)“输出: $(IntDir)\ $(InputName).obj如果要生成调试信息,可以将” / Zi“添加到命令行参数,您还可以根据需要生成.lst和.sbr文件. 如果要在汇编文件中调用Windows API,则可以从Internet下载MASM32程序包(包括MASM汇编工具,非常完整的Windows API头文件/库文件,实用宏以及大量的Win32编译)实例等). “ / IX: \ MASM32 \ INCLUDE”参数应添加到命令行以指定Windows API程序集头文件(.inc)的路径. MASM32的主页是: 您可以下载MASM32软件包的最新版本.


本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-195872-1.html

    相关阅读
      发表评论  请自觉遵守互联网相关的政策法规,严禁发布、暴力、反动的言论

      热点图片
      拼命载入中...