# include<stdio.h>
void main()
{
__asm
{
DATA SEGMENT
STRING1 DB 0DH,0AH,'Please input the first numbers:',0DH,0AH,'$'
STRING2 DB 0DH,0AH,'Please input the second numbers:',0DH,0AH,'$'
NUM1 DW 0
NUM2 DW 0
DATA ENDS
CODE SEGMENT
ASSUME CS:CODE,DS:DATA
START:MOV AX,DATA
MOV DS,AX
LEA DX,STRING1 ;9号功能,显示字符串1输入第一个数
MOV AH,09H
INT 21H
LP:
MOV AH,1
INT 21H
CMP AL,0DH ;当输入的字符为回车结束数据输入
JZ NEXT
SUB AL,30H
MOV AH,0
MOV CX,AX
MOV BX,10
MOV AX,NUM1
MUL BX
ADD AX,CX
MOV NUM1,AX
JMP LP
NEXT:
LEA DX,STRING2 ;9号功能,显示字符串2输入第二个数
MOV AH,09H
INT 21H
LP1:
MOV AH,1
INT 21H
CMP AL,0DH
JZ NEXT1 ;;当输入的字符为回车结束数据输入
SUB AL,30H
MOV AH,0
MOV CX,AX
MOV BX,10
MOV AX,NUM2
MUL BX
ADD AX,CX
MOV NUM2,AX
JMP LP1
NEXT1:
CALL DOO ;调用换行子程序
CALL A ;调用加法子程序
CALL DOO
CALL B ;调用减法子程序
CALL DOO
CALL C ;调用乘法子程序
CALL DOO
CALL D ;调用换行子程序
MOV AH,4CH ;返回DOS
INT 21H
A PROC NEAR ;加法子程序
MOV DX,NUM1
CALL PRINT ;调用数据以十进制输出子程序,把NUM1以十进制形式输出
MOV DL,'+'
CALL STDOUT ;调用输出子程序,把+号输出
MOV DX,NUM2
CALL PRINT
MOV DL,'=' ;调用输出子程序,把=号输出
CALL STDOUT
MOV AX,NUM1
ADD AX,NUM2
MOV DX,AX
CALL PRINT
RET
A ENDP
B PROC NEAR ;减法子程序
MOV DX,NUM1
CALL PRINT
MOV DL,'-'
CALL STDOUT
MOV DX,NUM2
CALL PRINT
MOV DL,'='
CALL STDOUT
MOV AX,NUM1
MOV BX,NUM2
SUB AX,BX
MOV DX,AX
CALL PRINT
RET
B ENDP
C PROC NEAR ;乘法子程序
MOV DX,NUM1
CALL PRINT
MOV DL,'*'
CALL STDOUT
MOV DX,NUM2
CALL PRINT
MOV DL,'='
CALL STDOUT
MOV AX,NUM1
MOV DX,0
MUL NUM2
MOV DX,AX
CALL PRINT
RET
C ENDP
D PROC NEAR ;除法子程序
MOV DX,NUM1
CALL PRINT
MOV DL,'/'
CALL STDOUT
MOV DX,NUM2
CALL PRINT
MOV DL,'='
CALL STDOUT
MOV DX,0
MOV AX,NUM1
DIV NUM2
MOV DX,AX
CALL PRINT
RET
D ENDP
PRINT PROC NEAR ;数据以十进制输出子程序
PUSH DX
PUSH AX
PUSH CX
PUSH BX
MOV CX,0
DO:MOV AX,DX
MOV DX,0
MOV BX,10
DIV BX
XCHG AX,DX
ADD AL,30H
PUSH AX
INC CX
CMP DX,0
JNZ DO
DO1:POP AX
MOV DL,AL
CALL STDOUT
LOOP DO1
POP BX
POP CX
POP AX
POP DX
RET
PRINT ENDP
STDOUT PROC NEAR ;输出子程序
MOV AH,2
INT 21H
RET
STDOUT ENDP
DOO PROC NEAR ;换行子程序
MOV AH,02H
MOV DL,0DH
INT 21H
MOV AH,02H
MOV DL,0AH
INT 21H
RET
DOO ENDP
CODE ENDS
END START
}
}
如上面的程序,编译的时候会报错。
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(6): error C2400: “操作码”中的内联汇编语法错误;找到“SEGMENT”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(7): error C2400: “操作码”中的内联汇编语法错误;找到“DB”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(7): error C2015: 常量中的字符太多
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(8): error C2400: “操作码”中的内联汇编语法错误;找到“DB”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(8): error C2015: 常量中的字符太多
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(9): error C2400: “操作码”中的内联汇编语法错误;找到“DW”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(10): error C2400: “操作码”中的内联汇编语法错误;找到“DW”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(11): error C2400: “操作码”中的内联汇编语法错误;找到“ENDS”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(12): error C2400: “操作码”中的内联汇编语法错误;找到“SEGMENT”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(13): warning C4405: “CS”: 标识符是保留字
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(13): error C2400: “操作码”中的内联汇编语法错误;找到“CS”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(14): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(30): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(33): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(50): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(53): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(68): error C2400: “操作码”中的内联汇编语法错误;找到“PROC”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(69): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(73): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(77): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(78): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(82): error C2400: “操作码”中的内联汇编语法错误;找到“ENDP”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(83): error C2400: “操作码”中的内联汇编语法错误;找到“PROC”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(84): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(88): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(92): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(93): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(98): error C2400: “操作码”中的内联汇编语法错误;找到“ENDP”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(99): error C2400: “操作码”中的内联汇编语法错误;找到“PROC”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(100): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(104): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(108): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(114): error C2400: “操作码”中的内联汇编语法错误;找到“ENDP”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(115): error C2400: “操作码”中的内联汇编语法错误;找到“PROC”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(116): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(120): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(125): error C2443: 操作数大小冲突
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(130): error C2400: “操作码”中的内联汇编语法错误;找到“ENDP”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(131): error C2400: “操作码”中的内联汇编语法错误;找到“PROC”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(156): error C2400: “操作码”中的内联汇编语法错误;找到“ENDP”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(157): error C2400: “操作码”中的内联汇编语法错误;找到“PROC”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(161): error C2400: “操作码”中的内联汇编语法错误;找到“ENDP”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(163): error C2400: “操作码”中的内联汇编语法错误;找到“PROC”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(171): error C2400: “操作码”中的内联汇编语法错误;找到“ENDP”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(172): error C2400: “操作码”中的内联汇编语法错误;找到“ENDS”
1>d:\documents\visual studio 2010\projects\调试1\调试1\调试1.cpp(173): error C2400: “操作码”中的内联汇编语法错误;找到“START”
谁知道该如何嵌套。
43 个解决方案
#1
作为一个新手,别人的程序都不会用。真悲哀啊。
#2
这种代码,别嵌入了,直接汇编就可以了
VC++ 内部有汇编器,可以直接用
如果嫌麻烦,可以到网上下载
masm32 //32BitsWindows,以及16Bits Dos 汇编器
masm615 //masm 6.15 版本。
VC++ 内部有汇编器,可以直接用
如果嫌麻烦,可以到网上下载
masm32 //32BitsWindows,以及16Bits Dos 汇编器
masm615 //masm 6.15 版本。
#3
请问VC++内部的汇编器怎么调用。没用过。
#4
直接在控制台 命令行输入 ml a.asm 就可以了
ml /? 可以得到帮助信息
ml /? 可以得到帮助信息
#5
在BC31下嵌入16位汇编
在VC下嵌入32位汇编
在VC下嵌入32位汇编
#7
以下内容摘自bc++3.1 asm联机帮助:
asm, _asm, __asm (keywords)
You use the asm statements to place assembly language statements in the
middle of your C++ source code.
Syntax:
asm <opcode> <operands> <; or newline>
_asm <opcode> <operands> <; or newline>
__asm <opcode> <operands> <; or newline>
Any C++ symbols are replaced by the appropriate assembly language
equivalents.
If you want to include a number of asm statements, surround them with
braces:
asm {
pop ax; pop ds
iret
}
Example
asm mov ax,_stklen
See Also:
BASM
asm, _asm, __asm (keywords)
You use the asm statements to place assembly language statements in the
middle of your C++ source code.
Syntax:
asm <opcode> <operands> <; or newline>
_asm <opcode> <operands> <; or newline>
__asm <opcode> <operands> <; or newline>
Any C++ symbols are replaced by the appropriate assembly language
equivalents.
If you want to include a number of asm statements, surround them with
braces:
asm {
pop ax; pop ds
iret
}
Example
asm mov ax,_stklen
See Also:
BASM
#8
没见过把完整的汇编语言源程序嵌进去的
#9
不是所有汇编指令都支持
#10
之前我根本不知道c语言的程序里面能嵌入汇编,那天老师说可以,我才知道。具体如何嵌入让我自己去搜
#11
主观能动性还是要发挥的。
#12
内联汇编仅限汇编指令
那些汇编器定义的宏, 像 SEGMENT, DB, DW 之类的是不支持的. 可以用 _emit 指令可以代替 db 之类的宏.
在内联汇编里面可以直接访问 C/C++ 里面的变量和函数, 很多时候还是比独立汇编方便.
那些汇编器定义的宏, 像 SEGMENT, DB, DW 之类的是不支持的. 可以用 _emit 指令可以代替 db 之类的宏.
在内联汇编里面可以直接访问 C/C++ 里面的变量和函数, 很多时候还是比独立汇编方便.
#13
仅供参考:
#pragma option -N-
//-------------------------------------------------------
#include <conio.h>
#include <dos.h>
#include <stdio.h>
//-------------------------------------------------------
#define YES 1
#define NO 0
#define CURSOR_MOVE 1
#define LEFT_DOWN 2
#define LEFT_UP 4
#define RIGHT_DOWN 8
#define RIGHT_UP 16
int MouseActive=NO,MouseMask,MouseButton,MouseX,MouseY;
//-------------------------------------------------------
void far mscall()
{
asm {
push ds
push si
xor si,si
mov ds,si
mov si,[0x40E]
mov ds,si
cmp ax,MouseMask
jne changed
cmp bx,MouseButton
jne changed
cmp cx,MouseX
jne changed
cmp dx,MouseY
je nochange
}
changed:
asm {
mov MouseMask,ax
mov MouseButton,bx
mov MouseX,cx
mov MouseY,dx
mov MouseActive,YES
jmp end
}
nochange:
asm {
mov MouseActive,NO
}
end:
asm {
pop si
pop ds
}
}
//-------------------------------------------------------
void MsLinkUserCall()
{
union REGS r;
struct SREGS sr;
*((int *)(0x0000040E))=FP_SEG(&MouseActive);
r.x.ax=0x0C;
r.x.cx=0x001F;
r.x.dx=FP_OFF(mscall);
sr.es=FP_SEG(mscall);
int86x(0x33,&r,&r,&sr);
}
//-------------------------------------------------------
int MsInstall()
{
void far *address;
union REGS regs;
address=getvect(0x33);
if((address==NULL)||(*(unsigned char *)address==0xCF)) return 0;
else {
regs.x.ax=0;
int86(0x33,®s,®s);
return regs.x.ax;
}
}
//-------------------------------------------------------
void MsShow()
{
union REGS regs;
regs.x.ax=1;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void MsHide()
{
union REGS regs;
regs.x.ax=2;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void MsSetLoc(x,y)
unsigned int x,y;
{
union REGS regs;
regs.x.ax=4;
regs.x.cx=x;
regs.x.dx=y;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void MsSetHoriLimit(l,r)
unsigned int l,r;
{
union REGS regs;
regs.x.ax=7;
regs.x.cx=l;
regs.x.dx=r;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void MsSetVertLimit(t,b)
unsigned int t,b;
{
union REGS regs;
regs.x.ax=8;
regs.x.cx=t;
regs.x.dx=b;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void main()
{
if (!MsInstall()) {
printf("I need a mouse.\n");
return;
}
clrscr();
MsLinkUserCall();
MsSetHoriLimit(0,638);
MsSetVertLimit(0,192);
MsSetLoc(0,0);
MsShow();
while (1) {
if (kbhit()) {
if (getch()==27) break;
}
if (MouseActive==YES) {
if (MouseMask&LEFT_DOWN) {
MsHide();printf(" LEFT_DOWN");MsShow();
}
if (MouseMask&LEFT_UP) {
MsHide();printf(" LEFT_UP");MsShow();
}
if (MouseMask&RIGHT_DOWN) {
MsHide();printf(" RIGHT_DOWN");MsShow();
}
if (MouseMask&RIGHT_UP) {
MsHide();printf(" RIGHT_UP");MsShow();
}
if (MouseButton&1) {
MsHide();printf(" LEFT_DRAG");MsShow();
}
if (MouseButton&2) {
MsHide();printf(" RIGHT_DRAG");MsShow();
}
if (MouseMask&CURSOR_MOVE) {
MsHide();printf(" MOVE_TO(%3d,%3d)",MouseX,MouseY);MsShow();
}
MsHide();printf("\n");MsShow();
MouseActive=NO;
}
}
MsHide();
MsInstall();
}
#14
VC++早就不支持生成16位程序,不论dos16、win16,你嵌入的是dos 16位汇编,根本不可能通过,而且还有一部分MASM语法在嵌入汇编中不支持。
#15
赵老师,你这个程序太有用了。之前我看了一堆如何嵌入的,总是晕头转向,正在用“alt+8”来盗取汇编源代码呢,突然看见这个程序,原来如此啊。看来在开学之前完成任务的可能性进一步增强了。谢谢你,赵老师。
#16
D:\BC\flc>dir mouse*.c
驱动器 D 中的卷是 Q_HD2_8
卷的序列号是 54FC-A4FD
D:\BC\flc 的目录
1998-03-31 14:55 3,428 MOUSETST.C
1 个文件 3,428 字节
0 个目录 16,783,536,128 可用字节
D:\BC\flc>
驱动器 D 中的卷是 Q_HD2_8
卷的序列号是 54FC-A4FD
D:\BC\flc 的目录
1998-03-31 14:55 3,428 MOUSETST.C
1 个文件 3,428 字节
0 个目录 16,783,536,128 可用字节
D:\BC\flc>
#17
提醒:
Win7下需要在DosBox中运行BC++3.1或TC
WinXP下,建一个批处理bc.bat,内容为下面两行,放在bc.exe同目录下,再将bc.bat发送到桌面快捷方式:
del tc*.swp >NUL
start command /c bc.exe
如果想在IDE里面使用鼠标,还应将快捷方式属性中的快速编辑模式关掉。
Win7下需要在DosBox中运行BC++3.1或TC
WinXP下,建一个批处理bc.bat,内容为下面两行,放在bc.exe同目录下,再将bc.bat发送到桌面快捷方式:
del tc*.swp >NUL
start command /c bc.exe
如果想在IDE里面使用鼠标,还应将快捷方式属性中的快速编辑模式关掉。
#18
啊,赵老师,你说的我不太懂。嗯,首先你这个程序我只是看了他的结构,如何在C语言中整段的定义使用汇编语言的。对于程序的内容我没有细看,刚才你一说与鼠标相关的话题,我没听懂。你这个程序是讲如何在BC下使用鼠标吗?可是我记得BC下本来就可以使用鼠标啊。
#19
我是担心你在比如Win7下或Win7 64位下用不了BC
#20
啊,赵老师,你说的我不太懂。嗯,首先你这个程序我只是看了他的结构,如何在C语言中整段的定义使用汇编语言的。对于程序的内容我没有细看,刚才你一说与鼠标相关的话题,我没听懂。你这个程序是讲如何在BC下使用鼠标吗?可是我记得BC下本来就可以使用鼠标啊。
提醒:
Win7下需要在DosBox中运行BC++3.1或TC
WinXP下,建一个批处理bc.bat,内容为下面两行,放在bc.exe同目录下,再将bc.bat发送到桌面快捷方式:
del tc*.swp >NUL
start command /c bc.exe
如果想在IDE里面使用鼠标,还应将快捷方式属性中的快速编辑模式关掉。
我是担心你在比如Win7下或Win7 64位下用不了BC
啊,赵老师,你说的我不太懂。嗯,首先你这个程序我只是看了他的结构,如何在C语言中整段的定义使用汇编语言的。对于程序的内容我没有细看,刚才你一说与鼠标相关的话题,我没听懂。你这个程序是讲如何在BC下使用鼠标吗?可是我记得BC下本来就可以使用鼠标啊。
提醒:
Win7下需要在DosBox中运行BC++3.1或TC
WinXP下,建一个批处理bc.bat,内容为下面两行,放在bc.exe同目录下,再将bc.bat发送到桌面快捷方式:
del tc*.swp >NUL
start command /c bc.exe
如果想在IDE里面使用鼠标,还应将快捷方式属性中的快速编辑模式关掉。
我是担心你在比如Win7下或Win7 64位下用不了BC
#21
VS2010只能嵌入32位汇编,嵌入不了16位或64位汇编。
32位汇编参考下面:
32位汇编参考下面:
X86和X87汇编指令大全(有注释)
---------- 一、数据传输指令 ----------------------------------------------------
它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.
1. 通用数据传送指令.
MOV 传送字或字节.
MOVSX 先符号扩展,再传送.
MOVZX 先零扩展,再传送.
PUSH 把字压入堆栈.
POP 把字弹出堆栈.
PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.
POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.
PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.
POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.
BSWAP 交换32位寄存器里字节的顺序
XCHG 交换字或字节.(至少有一个操作数为寄存器,段寄存器不可作为操作数)
CMPXCHG 比较并交换操作数.(第二个操作数必须为累加器AL/AX/EAX)
XADD 先交换再累加.(结果在第一个操作数里)
XLAT 字节查表转换.----BX指向一张256字节的表的起点,AL为表的索引值(0-255,即0-FFH);返回AL为查表结果.([BX+AL]->AL)
2. 输入输出端口传送指令.
IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )
OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器 )输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时,其范围是 0-65535.
3. 目的地址传送指令.
LEA 装入有效地址.例: LEA DX,string ;把偏移地址存到DX.
LDS 传送目标指针,把指针内容装入DS.例: LDS SI,string ;把段地址:偏移地址存到DS:SI.
LES 传送目标指针,把指针内容装入ES.例: LES DI,string ;把段地址:偏移地址存到ES:DI.
LFS 传送目标指针,把指针内容装入FS.例: LFS DI,string ;把段地址:偏移地址存到FS:DI.
LGS 传送目标指针,把指针内容装入GS.例: LGS DI,string ;把段地址:偏移地址存到GS:DI.
LSS 传送目标指针,把指针内容装入SS.例: LSS DI,string ;把段地址:偏移地址存到SS:DI.
4. 标志传送指令.
LAHF 标志寄存器传送,把标志装入AH.
SAHF 标志寄存器传送,把AH内容装入标志寄存器.
PUSHF 标志入栈.
POPF 标志出栈.
PUSHD 32位标志入栈.
POPD 32位标志出栈.
---------- 二、算术运算指令 ----------------------------------------------------
ADD 加法.
ADC 带进位加法.
INC 加 1.
AAA 加法的ASCII码调整.
DAA 加法的十进制调整.
SUB 减法.
SBB 带借位减法.
DEC 减 1.
NEG 求反(以 0 减之).
CMP 比较.(两操作数作减法,仅修改标志位,不回送结果).
AAS 减法的ASCII码调整.
DAS 减法的十进制调整.
MUL 无符号乘法.结果回送AH和AL(字节运算),或DX和AX(字运算),
IMUL 整数乘法.结果回送AH和AL(字节运算),或DX和AX(字运算),
AAM 乘法的ASCII码调整.
DIV 无符号除法.结果回送:商回送AL,余数回送AH, (字节运算);或 商回送AX,余数回送DX, (字运算).
IDIV 整数除法.结果回送:商回送AL,余数回送AH, (字节运算);或 商回送AX,余数回送DX, (字运算).
AAD 除法的ASCII码调整.
CBW 字节转换为字. (把AL中字节的符号扩展到AH中去)
CWD 字转换为双字. (把AX中的字的符号扩展到DX中去)
CWDE 字转换为双字. (把AX中的字符号扩展到EAX中去)
CDQ 双字扩展. (把EAX中的字的符号扩展到EDX中去)
---------- 三、逻辑运算指令 ----------------------------------------------------
AND 与运算.
OR 或运算.
XOR 异或运算.
NOT 取反.
TEST 测试.(两操作数作与运算,仅修改标志位,不回送结果).
SHL 逻辑左移.
SAL 算术左移.(=SHL)
SHR 逻辑右移.
SAR 算术右移.(=SHR)
ROL 循环左移.
ROR 循环右移.
RCL 通过进位的循环左移.
RCR 通过进位的循环右移.
以上八种移位指令,其移位次数可达255次.
移位一次时, 可直接用操作码. 如 SHL AX,1.
移位>1次时, 则由寄存器CL给出移位次数.
如 MOV CL,04 SHL AX,CL
---------- 四、串指令 ----------------------------------------------------------
DS:SI 源串段寄存器 :源串变址.
ES:DI 目标串段寄存器:目标串变址.
CX 重复次数计数器.
AL/AX 扫描值.
D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量.
Z标志 用来控制扫描或比较操作的结束.
MOVS 串传送.( MOVSB 传送字符. MOVSW 传送字. MOVSD 传送双字. )
CMPS 串比较.( CMPSB 比较字符. CMPSW 比较字. )
SCAS 串扫描.把AL或AX的内容与目标串作比较,比较结果反映在标志位.
LODS 装入串.把源串中的元素(字或字节)逐一装入AL或AX中.( LODSB 传送字符. LODSW 传送字. LODSD 传送双字. )
STOS 保存串.是LODS的逆过程.
REP 当CX/ECX<>0时重复.
REPE/REPZ 当ZF=1或比较结果相等,且CX/ECX<>0时重复.
REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复.
REPC 当CF=1且CX/ECX<>0时重复.
REPNC 当CF=0且CX/ECX<>0时重复.
---------- 五、程序转移指令 ----------------------------------------------------
1. 无条件转移指令 (长转移)
JMP 无条件转移指令
CALL 过程调用
RET/RETF 过程返回.
2. 条件转移指令 (短转移,-128到+127的距离内)( 当且仅当(SF XOR OF)=1时,OP1<OP2 )
JA/JNBE 不小于或不等于时转移.
JAE/JNB 大于或等于转移.
JB/JNAE 小于转移.
JBE/JNA 小于或等于转移.
以上四条,测试无符号整数运算的结果(标志C和Z).
JG/JNLE 大于转移.
JGE/JNL 大于或等于转移.
JL/JNGE 小于转移.
JLE/JNG 小于或等于转移.
以上四条,测试带符号整数运算的结果(标志S,O和Z).
JE/JZ 等于转移.
JNE/JNZ 不等于时转移.
JC 有进位时转移.
JNC 无进位时转移.
JNO 不溢出时转移.
JNP/JPO 奇偶性为奇数时转移.
JNS 符号位为 "0" 时转移.
JO 溢出转移.
JP/JPE 奇偶性为偶数时转移.
JS 符号位为 "1" 时转移.
3. 循环控制指令(短转移)
LOOP CX不为零时循环.
LOOPE/LOOPZ CX不为零且标志Z=1时循环.
LOOPNE/LOOPNZ CX不为零且标志Z=0时循环.
JCXZ CX为零时转移.
JECXZ ECX为零时转移.
4. 中断指令
INT 中断指令
INTO 溢出中断
IRET 中断返回
5. 处理器控制指令
HLT 处理器暂停, 直到出现中断或复位信号才继续.
WAIT 当芯片引线TEST为高电平时使CPU进入等待状态.
ESC 转换到外处理器.
LOCK *总线.
NOP 空操作.
STC 置进位标志位.
CLC 清进位标志位.
CMC 进位标志取反.
STD 置方向标志位.
CLD 清方向标志位.
STI 置中断允许位.
CLI 清中断允许位.
---------- 六、伪指令 ----------------------------------------------------------
DW 定义字(2字节).
PROC 定义过程.
ENDP 过程结束.
SEGMENT 定义段.
ASSUME 建立段寄存器寻址.
ENDS 段结束.
END 程序结束.
---------- 七、处理机控制指令:标志处理指令 ------------------------------------
CLC 进位位置0指令
CMC 进位位求反指令
STC 进位位置为1指令
CLD 方向标志置1指令
STD 方向标志位置1指令
CLI 中断标志置0指令
STI 中断标志置1指令
NOP 无操作
HLT 停机
WAIT 等待
ESC 换码
LOCK *
========== 浮点运算指令集 ======================================================
---------- 一、控制指令(带9B的控制指令前缀F变为FN时浮点不检查,机器码去掉9B)----
FINIT 初始化浮点部件 机器码 9B DB E3
FCLEX 清除异常 机器码 9B DB E2
FDISI 浮点检查禁止中断 机器码 9B DB E1
FENI 浮点检查禁止中断二 机器码 9B DB E0
WAIT 同步CPU和FPU 机器码 9B
FWAIT 同步CPU和FPU 机器码 D9 D0
FNOP 无操作 机器码 DA E9
FXCH 交换ST(0)和ST(1) 机器码 D9 C9
FXCH ST(i) 交换ST(0)和ST(i) 机器码 D9 C1iii
FSTSW ax 状态字到ax 机器码 9B DF E0
FSTSW word ptr mem 状态字到mem 机器码 9B DD mm111mmm
FLDCW word ptr mem mem到状态字 机器码 D9 mm101mmm
FSTCW word ptr mem 控制字到mem 机器码 9B D9 mm111mmm
FLDENV word ptr mem mem到全环境 机器码 D9 mm100mmm
FSTENV word ptr mem 全环境到mem 机器码 9B D9 mm110mmm
FRSTOR word ptr mem mem到FPU状态 机器码 DD mm100mmm
FSAVE word ptr mem FPU状态到mem 机器码 9B DD mm110mmm
FFREE ST(i) 标志ST(i)未使用 机器码 DD C0iii
FDECSTP 减少栈指针1->0 2->1 机器码 D9 F6
FINCSTP 增加栈指针0->1 1->2 机器码 D9 F7
FSETPM 浮点设置保护 机器码 DB E4
---------- 二、数据传送指令 ----------------------------------------------------
FLDZ 将0.0装入ST(0) 机器码 D9 EE
FLD1 将1.0装入ST(0) 机器码 D9 E8
FLDPI 将π装入ST(0) 机器码 D9 EB
FLDL2T 将ln10/ln2装入ST(0) 机器码 D9 E9
FLDL2E 将1/ln2装入ST(0) 机器码 D9 EA
FLDLG2 将ln2/ln10装入ST(0) 机器码 D9 EC
FLDLN2 将ln2装入ST(0) 机器码 D9 ED
FLD real4 ptr mem 装入mem的单精度浮点数 机器码 D9 mm000mmm
FLD real8 ptr mem 装入mem的双精度浮点数 机器码 DD mm000mmm
FLD real10 ptr mem 装入mem的十字节浮点数 机器码 DB mm101mmm
FILD word ptr mem 装入mem的二字节整数 机器码 DF mm000mmm
FILD dword ptr mem 装入mem的四字节整数 机器码 DB mm000mmm
FILD qword ptr mem 装入mem的八字节整数 机器码 DF mm101mmm
FBLD tbyte ptr mem 装入mem的十字节BCD数 机器码 DF mm100mmm
FST real4 ptr mem 保存单精度浮点数到mem 机器码 D9 mm010mmm
FST real8 ptr mem 保存双精度浮点数到mem 机器码 DD mm010mmm
FIST word ptr mem 保存二字节整数到mem 机器码 DF mm010mmm
FIST dword ptr mem 保存四字节整数到mem 机器码 DB mm010mmm
FSTP real4 ptr mem 保存单精度浮点数到mem并出栈 机器码 D9 mm011mmm
FSTP real8 ptr mem 保存双精度浮点数到mem并出栈 机器码 DD mm011mmm
FSTP real10 ptr mem 保存十字节浮点数到mem并出栈 机器码 DB mm111mmm
FISTP word ptr mem 保存二字节整数到mem并出栈 机器码 DF mm011mmm
FISTP dword ptr mem 保存四字节整数到mem并出栈 机器码 DB mm011mmm
FISTP qword ptr mem 保存八字节整数到mem并出栈 机器码 DF mm111mmm
FBSTP tbyte ptr mem 保存十字节BCD数到mem并出栈 机器码 DF mm110mmm
FCMOVB ST(0),ST(i) <时传送 机器码 DA C0iii
FCMOVBE ST(0),ST(i) <=时传送 机器码 DA D0iii
FCMOVE ST(0),ST(i) =时传送 机器码 DA C1iii
FCMOVNB ST(0),ST(i) >=时传送 机器码 DB C0iii
FCMOVNBE ST(0),ST(i) >时传送 机器码 DB D0iii
FCMOVNE ST(0),ST(i) !=时传送 机器码 DB C1iii
FCMOVNU ST(0),ST(i) 有序时传送 机器码 DB D1iii
FCMOVU ST(0),ST(i) 无序时传送 机器码 DA D1iii
---------- 三、比较指令 --------------------------------------------------------
FCOM ST(0)-ST(1) 机器码 D8 D1
FCOMI ST(0),ST(i) ST(0)-ST(1) 机器码 DB F0iii
FCOMIP ST(0),ST(i) ST(0)-ST(1)并出栈 机器码 DF F0iii
FCOM real4 ptr mem ST(0)-实数mem 机器码 D8 mm010mmm
FCOM real8 ptr mem ST(0)-实数mem 机器码 DC mm010mmm
FICOM word ptr mem ST(0)-整数mem 机器码 DE mm010mmm
FICOM dword ptr mem ST(0)-整数mem 机器码 DA mm010mmm
FICOMP word ptr mem ST(0)-整数mem并出栈 机器码 DE mm011mmm
FICOMP dword ptr mem ST(0)-整数mem并出栈 机器码 DA mm011mmm
FTST ST(0)-0 机器码 D9 E4
FUCOM ST(i) ST(0)-ST(i) 机器码 DD E0iii
FUCOMP ST(i) ST(0)-ST(i)并出栈 机器码 DD E1iii
FUCOMPP ST(0)-ST(1)并二次出栈 机器码 DA E9
FXAM ST(0)规格类型 机器码 D9 E5
---------- 四、运算指令 --------------------------------------------------------
FADD 把目的操作数 (直接接在指令后的变量或堆栈缓存器) 与来源操作数 (接在目的操作数后的变量或堆栈缓存器) 相加,并将结果存入目的操作数
FADDP ST(i),ST 这个指令是使目的操作数加上 ST 缓存器,并弹出 ST 缓存器,而目的操作数必须是堆栈缓存器的其中之一,最后不管目的操作数为何,经弹出一次后,目的操作数会变成上一个堆栈缓存器了
FIADD FIADD 是把 ST 加上来源操作数,然后再存入 ST 缓存器,来源操作数必须是字组整数或短整数形态的变数
FSUB 减
FSUBP
FSUBR 减数与被减数互换
FSUBRP
FISUB
FISUBR
FMUL 乘
FMULP
FIMUL
FDIV 除
FDIVP
FDIVR
FDIVRP
FIDIV
FIDIVR
FCHS 改变 ST 的正负值
FABS 把 ST 之值取出,取其绝对值后再存回去。
FSQRT 将 ST 之值取出,开根号后再存回去。
FSCALE 这个指令是计算 ST*2^ST(1)之值,再把结果存入 ST 里而 ST(1) 之值不变。ST(1) 必须是在 -32768 到 32768 (-215 到 215 )之间的整数,如果超过这个范围计算结果无法确定,如果不是整数 ST(1) 会先向零舍入成整数再计算。所以为安全起见,最好是由字组整数载入到 ST(1) 里。
FRNDINT 这个指令是把 ST 的数值舍入成整数,FPU 提供四种舍入方式,由 FPU 的控制字组(control word)中的 RC 两个位决定
RC 舍入控制
00 四舍五入
01 向负无限大舍入
10 向正无限大舍入
11 向零舍去
================================================================================
#22
VS2010只能嵌入32位汇编,嵌入不了16位或64位汇编。
32位汇编参考下面:X86和X87汇编指令大全(有注释)
---------- 一、数据传输指令 ----------------------------------------------------
它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.
1. 通用数据传送指令.
MOV 传送字或字节.
MOVSX 先符号扩展,再传送.
MOVZX 先零扩展,再传送.
PUSH 把字压入堆栈.
POP 把字弹出堆栈.
PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.
POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.
PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.
POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.
BSWAP 交换32位寄存器里字节的顺序
XCHG 交换字或字节.(至少有一个操作数为寄存器,段寄存器不可作为操作数)
CMPXCHG 比较并交换操作数.(第二个操作数必须为累加器AL/AX/EAX)
XADD 先交换再累加.(结果在第一个操作数里)
XLAT 字节查表转换.----BX指向一张256字节的表的起点,AL为表的索引值(0-255,即0-FFH);返回AL为查表结果.([BX+AL]->AL)
2. 输入输出端口传送指令.
IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )
OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器 )输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时,其范围是 0-65535.
3. 目的地址传送指令.
LEA 装入有效地址.例: LEA DX,string ;把偏移地址存到DX.
LDS 传送目标指针,把指针内容装入DS.例: LDS SI,string ;把段地址:偏移地址存到DS:SI.
LES 传送目标指针,把指针内容装入ES.例: LES DI,string ;把段地址:偏移地址存到ES:DI.
LFS 传送目标指针,把指针内容装入FS.例: LFS DI,string ;把段地址:偏移地址存到FS:DI.
LGS 传送目标指针,把指针内容装入GS.例: LGS DI,string ;把段地址:偏移地址存到GS:DI.
LSS 传送目标指针,把指针内容装入SS.例: LSS DI,string ;把段地址:偏移地址存到SS:DI.
4. 标志传送指令.
LAHF 标志寄存器传送,把标志装入AH.
SAHF 标志寄存器传送,把AH内容装入标志寄存器.
PUSHF 标志入栈.
POPF 标志出栈.
PUSHD 32位标志入栈.
POPD 32位标志出栈.
---------- 二、算术运算指令 ----------------------------------------------------
ADD 加法.
ADC 带进位加法.
INC 加 1.
AAA 加法的ASCII码调整.
DAA 加法的十进制调整.
SUB 减法.
SBB 带借位减法.
DEC 减 1.
NEG 求反(以 0 减之).
CMP 比较.(两操作数作减法,仅修改标志位,不回送结果).
AAS 减法的ASCII码调整.
DAS 减法的十进制调整.
MUL 无符号乘法.结果回送AH和AL(字节运算),或DX和AX(字运算),
IMUL 整数乘法.结果回送AH和AL(字节运算),或DX和AX(字运算),
AAM 乘法的ASCII码调整.
DIV 无符号除法.结果回送:商回送AL,余数回送AH, (字节运算);或 商回送AX,余数回送DX, (字运算).
IDIV 整数除法.结果回送:商回送AL,余数回送AH, (字节运算);或 商回送AX,余数回送DX, (字运算).
AAD 除法的ASCII码调整.
CBW 字节转换为字. (把AL中字节的符号扩展到AH中去)
CWD 字转换为双字. (把AX中的字的符号扩展到DX中去)
CWDE 字转换为双字. (把AX中的字符号扩展到EAX中去)
CDQ 双字扩展. (把EAX中的字的符号扩展到EDX中去)
---------- 三、逻辑运算指令 ----------------------------------------------------
AND 与运算.
OR 或运算.
XOR 异或运算.
NOT 取反.
TEST 测试.(两操作数作与运算,仅修改标志位,不回送结果).
SHL 逻辑左移.
SAL 算术左移.(=SHL)
SHR 逻辑右移.
SAR 算术右移.(=SHR)
ROL 循环左移.
ROR 循环右移.
RCL 通过进位的循环左移.
RCR 通过进位的循环右移.
以上八种移位指令,其移位次数可达255次.
移位一次时, 可直接用操作码. 如 SHL AX,1.
移位>1次时, 则由寄存器CL给出移位次数.
如 MOV CL,04 SHL AX,CL
---------- 四、串指令 ----------------------------------------------------------
DS:SI 源串段寄存器 :源串变址.
ES:DI 目标串段寄存器:目标串变址.
CX 重复次数计数器.
AL/AX 扫描值.
D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量.
Z标志 用来控制扫描或比较操作的结束.
MOVS 串传送.( MOVSB 传送字符. MOVSW 传送字. MOVSD 传送双字. )
CMPS 串比较.( CMPSB 比较字符. CMPSW 比较字. )
SCAS 串扫描.把AL或AX的内容与目标串作比较,比较结果反映在标志位.
LODS 装入串.把源串中的元素(字或字节)逐一装入AL或AX中.( LODSB 传送字符. LODSW 传送字. LODSD 传送双字. )
STOS 保存串.是LODS的逆过程.
REP 当CX/ECX<>0时重复.
REPE/REPZ 当ZF=1或比较结果相等,且CX/ECX<>0时重复.
REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复.
REPC 当CF=1且CX/ECX<>0时重复.
REPNC 当CF=0且CX/ECX<>0时重复.
---------- 五、程序转移指令 ----------------------------------------------------
1. 无条件转移指令 (长转移)
JMP 无条件转移指令
CALL 过程调用
RET/RETF 过程返回.
2. 条件转移指令 (短转移,-128到+127的距离内)( 当且仅当(SF XOR OF)=1时,OP1<OP2 )
JA/JNBE 不小于或不等于时转移.
JAE/JNB 大于或等于转移.
JB/JNAE 小于转移.
JBE/JNA 小于或等于转移.
以上四条,测试无符号整数运算的结果(标志C和Z).
JG/JNLE 大于转移.
JGE/JNL 大于或等于转移.
JL/JNGE 小于转移.
JLE/JNG 小于或等于转移.
以上四条,测试带符号整数运算的结果(标志S,O和Z).
JE/JZ 等于转移.
JNE/JNZ 不等于时转移.
JC 有进位时转移.
JNC 无进位时转移.
JNO 不溢出时转移.
JNP/JPO 奇偶性为奇数时转移.
JNS 符号位为 "0" 时转移.
JO 溢出转移.
JP/JPE 奇偶性为偶数时转移.
JS 符号位为 "1" 时转移.
3. 循环控制指令(短转移)
LOOP CX不为零时循环.
LOOPE/LOOPZ CX不为零且标志Z=1时循环.
LOOPNE/LOOPNZ CX不为零且标志Z=0时循环.
JCXZ CX为零时转移.
JECXZ ECX为零时转移.
4. 中断指令
INT 中断指令
INTO 溢出中断
IRET 中断返回
5. 处理器控制指令
HLT 处理器暂停, 直到出现中断或复位信号才继续.
WAIT 当芯片引线TEST为高电平时使CPU进入等待状态.
ESC 转换到外处理器.
LOCK *总线.
NOP 空操作.
STC 置进位标志位.
CLC 清进位标志位.
CMC 进位标志取反.
STD 置方向标志位.
CLD 清方向标志位.
STI 置中断允许位.
CLI 清中断允许位.
---------- 六、伪指令 ----------------------------------------------------------
DW 定义字(2字节).
PROC 定义过程.
ENDP 过程结束.
SEGMENT 定义段.
ASSUME 建立段寄存器寻址.
ENDS 段结束.
END 程序结束.
---------- 七、处理机控制指令:标志处理指令 ------------------------------------
CLC 进位位置0指令
CMC 进位位求反指令
STC 进位位置为1指令
CLD 方向标志置1指令
STD 方向标志位置1指令
CLI 中断标志置0指令
STI 中断标志置1指令
NOP 无操作
HLT 停机
WAIT 等待
ESC 换码
LOCK *
========== 浮点运算指令集 ======================================================
---------- 一、控制指令(带9B的控制指令前缀F变为FN时浮点不检查,机器码去掉9B)----
FINIT 初始化浮点部件 机器码 9B DB E3
FCLEX 清除异常 机器码 9B DB E2
FDISI 浮点检查禁止中断 机器码 9B DB E1
FENI 浮点检查禁止中断二 机器码 9B DB E0
WAIT 同步CPU和FPU 机器码 9B
FWAIT 同步CPU和FPU 机器码 D9 D0
FNOP 无操作 机器码 DA E9
FXCH 交换ST(0)和ST(1) 机器码 D9 C9
FXCH ST(i) 交换ST(0)和ST(i) 机器码 D9 C1iii
FSTSW ax 状态字到ax 机器码 9B DF E0
FSTSW word ptr mem 状态字到mem 机器码 9B DD mm111mmm
FLDCW word ptr mem mem到状态字 机器码 D9 mm101mmm
FSTCW word ptr mem 控制字到mem 机器码 9B D9 mm111mmm
FLDENV word ptr mem mem到全环境 机器码 D9 mm100mmm
FSTENV word ptr mem 全环境到mem 机器码 9B D9 mm110mmm
FRSTOR word ptr mem mem到FPU状态 机器码 DD mm100mmm
FSAVE word ptr mem FPU状态到mem 机器码 9B DD mm110mmm
FFREE ST(i) 标志ST(i)未使用 机器码 DD C0iii
FDECSTP 减少栈指针1->0 2->1 机器码 D9 F6
FINCSTP 增加栈指针0->1 1->2 机器码 D9 F7
FSETPM 浮点设置保护 机器码 DB E4
---------- 二、数据传送指令 ----------------------------------------------------
FLDZ 将0.0装入ST(0) 机器码 D9 EE
FLD1 将1.0装入ST(0) 机器码 D9 E8
FLDPI 将π装入ST(0) 机器码 D9 EB
FLDL2T 将ln10/ln2装入ST(0) 机器码 D9 E9
FLDL2E 将1/ln2装入ST(0) 机器码 D9 EA
FLDLG2 将ln2/ln10装入ST(0) 机器码 D9 EC
FLDLN2 将ln2装入ST(0) 机器码 D9 ED
FLD real4 ptr mem 装入mem的单精度浮点数 机器码 D9 mm000mmm
FLD real8 ptr mem 装入mem的双精度浮点数 机器码 DD mm000mmm
FLD real10 ptr mem 装入mem的十字节浮点数 机器码 DB mm101mmm
FILD word ptr mem 装入mem的二字节整数 机器码 DF mm000mmm
FILD dword ptr mem 装入mem的四字节整数 机器码 DB mm000mmm
FILD qword ptr mem 装入mem的八字节整数 机器码 DF mm101mmm
FBLD tbyte ptr mem 装入mem的十字节BCD数 机器码 DF mm100mmm
FST real4 ptr mem 保存单精度浮点数到mem 机器码 D9 mm010mmm
FST real8 ptr mem 保存双精度浮点数到mem 机器码 DD mm010mmm
FIST word ptr mem 保存二字节整数到mem 机器码 DF mm010mmm
FIST dword ptr mem 保存四字节整数到mem 机器码 DB mm010mmm
FSTP real4 ptr mem 保存单精度浮点数到mem并出栈 机器码 D9 mm011mmm
FSTP real8 ptr mem 保存双精度浮点数到mem并出栈 机器码 DD mm011mmm
FSTP real10 ptr mem 保存十字节浮点数到mem并出栈 机器码 DB mm111mmm
FISTP word ptr mem 保存二字节整数到mem并出栈 机器码 DF mm011mmm
FISTP dword ptr mem 保存四字节整数到mem并出栈 机器码 DB mm011mmm
FISTP qword ptr mem 保存八字节整数到mem并出栈 机器码 DF mm111mmm
FBSTP tbyte ptr mem 保存十字节BCD数到mem并出栈 机器码 DF mm110mmm
FCMOVB ST(0),ST(i) <时传送 机器码 DA C0iii
FCMOVBE ST(0),ST(i) <=时传送 机器码 DA D0iii
FCMOVE ST(0),ST(i) =时传送 机器码 DA C1iii
FCMOVNB ST(0),ST(i) >=时传送 机器码 DB C0iii
FCMOVNBE ST(0),ST(i) >时传送 机器码 DB D0iii
FCMOVNE ST(0),ST(i) !=时传送 机器码 DB C1iii
FCMOVNU ST(0),ST(i) 有序时传送 机器码 DB D1iii
FCMOVU ST(0),ST(i) 无序时传送 机器码 DA D1iii
---------- 三、比较指令 --------------------------------------------------------
FCOM ST(0)-ST(1) 机器码 D8 D1
FCOMI ST(0),ST(i) ST(0)-ST(1) 机器码 DB F0iii
FCOMIP ST(0),ST(i) ST(0)-ST(1)并出栈 机器码 DF F0iii
FCOM real4 ptr mem ST(0)-实数mem 机器码 D8 mm010mmm
FCOM real8 ptr mem ST(0)-实数mem 机器码 DC mm010mmm
FICOM word ptr mem ST(0)-整数mem 机器码 DE mm010mmm
FICOM dword ptr mem ST(0)-整数mem 机器码 DA mm010mmm
FICOMP word ptr mem ST(0)-整数mem并出栈 机器码 DE mm011mmm
FICOMP dword ptr mem ST(0)-整数mem并出栈 机器码 DA mm011mmm
FTST ST(0)-0 机器码 D9 E4
FUCOM ST(i) ST(0)-ST(i) 机器码 DD E0iii
FUCOMP ST(i) ST(0)-ST(i)并出栈 机器码 DD E1iii
FUCOMPP ST(0)-ST(1)并二次出栈 机器码 DA E9
FXAM ST(0)规格类型 机器码 D9 E5
---------- 四、运算指令 --------------------------------------------------------
FADD 把目的操作数 (直接接在指令后的变量或堆栈缓存器) 与来源操作数 (接在目的操作数后的变量或堆栈缓存器) 相加,并将结果存入目的操作数
FADDP ST(i),ST 这个指令是使目的操作数加上 ST 缓存器,并弹出 ST 缓存器,而目的操作数必须是堆栈缓存器的其中之一,最后不管目的操作数为何,经弹出一次后,目的操作数会变成上一个堆栈缓存器了
FIADD FIADD 是把 ST 加上来源操作数,然后再存入 ST 缓存器,来源操作数必须是字组整数或短整数形态的变数
FSUB 减
FSUBP
FSUBR 减数与被减数互换
FSUBRP
FISUB
FISUBR
FMUL 乘
FMULP
FIMUL
FDIV 除
FDIVP
FDIVR
FDIVRP
FIDIV
FIDIVR
FCHS 改变 ST 的正负值
FABS 把 ST 之值取出,取其绝对值后再存回去。
FSQRT 将 ST 之值取出,开根号后再存回去。
FSCALE 这个指令是计算 ST*2^ST(1)之值,再把结果存入 ST 里而 ST(1) 之值不变。ST(1) 必须是在 -32768 到 32768 (-215 到 215 )之间的整数,如果超过这个范围计算结果无法确定,如果不是整数 ST(1) 会先向零舍入成整数再计算。所以为安全起见,最好是由字组整数载入到 ST(1) 里。
FRNDINT 这个指令是把 ST 的数值舍入成整数,FPU 提供四种舍入方式,由 FPU 的控制字组(control word)中的 RC 两个位决定
RC 舍入控制
00 四舍五入
01 向负无限大舍入
10 向正无限大舍入
11 向零舍去
================================================================================
#23
《The Intel 64 and IA-32 Architectures Software Developer's Manual》
#24
再供参考:
#include <stdio.h>
float data[500];
int i;
void main() {
for (i=0;i<500;i++) {data[i]=1.0f;printf("%g\n",data[i]);}
__asm {
push ecx
push edi
mov ecx,500
mov eax,0xBF800000 //-1.0f
lea edi,data
rep stosd
pop edi
pop ecx
}
for (i=0;i<500;i++) printf("%g\n",data[i]);
}
#25
再供参考:#include <stdio.h>
float data[500];
int i;
void main() {
for (i=0;i<500;i++) {data[i]=1.0f;printf("%g\n",data[i]);}
__asm {
push ecx
push edi
mov ecx,500
mov eax,0xBF800000 //-1.0f
lea edi,data
rep stosd
pop edi
pop ecx
}
for (i=0;i<500;i++) printf("%g\n",data[i]);
}
#27
@赵4老师
我先是把程序写成了C语言的形式,就是这一段,用来实现大整数相加的。然后在调试的时候,按“alt+8”,反汇编,然后把反汇编的代码粘贴到相应的位置。结果是,C语言产生的结果正确,而嵌入了汇编的程序,结果完全错误。嗯,应该说是从第三位开始出错。
一下是C语言代码,
然后是反汇编出来的。
,最后是我嵌入的,因为要涉及到跳转,反汇编出来的跳转位置我无法确定,只好把他们分割成不同的小段。
我先是把程序写成了C语言的形式,就是这一段,用来实现大整数相加的。然后在调试的时候,按“alt+8”,反汇编,然后把反汇编的代码粘贴到相应的位置。结果是,C语言产生的结果正确,而嵌入了汇编的程序,结果完全错误。嗯,应该说是从第三位开始出错。
一下是C语言代码,
#include <stdio.h>
#define MAXINT 20
int bigplus(unsigned char a[],unsigned char b[],unsigned char c[]);
int main(int argc, char *argv[])
{
unsigned char a[MAXINT]={10,5,4,6,5,4,3,2,1,1,1}; //被乘数或被除数
unsigned char b[MAXINT]={7,7,6,5,4,3,2,1}; //乘数或除数
unsigned char c[MAXINT],d[MAXINT]; //c[]存放商,d[]存放余数
int div=1234; //小乘数或小除数
int k=0;
int *res=&k; //小余数整数指针
bigplus(a,b,c);
getchar();
return 0;
}
int bigplus(unsigned char a[],unsigned char b[],unsigned char c[]) //大整数加法
{
int i,len;
len=(a[0]>b[0]?a[0]:b[0]); //a[0] b[0]保存数组长度,len为较长的一个
for(i=0;i<MAXINT;i++) //将数组清0
c[i]=0;
for (i=1;i<=len;i++) //计算每一位的值
{
c[i]+=(a[i]+b[i]);
if (c[i]>=10)
{
c[i]-=10; //大于10的取个位
c[i+1]++; //高位加1
}
}
if (c[i+1]>0) len++;
c[0]=len; //c[0]保存结果数组实际长度
printf("Big integers add: ");
for (i=len;i>=1;i--)
printf("%d",c[i]); //打印结果
printf("\n");
return 0;
}
然后是反汇编出来的。
,最后是我嵌入的,因为要涉及到跳转,反汇编出来的跳转位置我无法确定,只好把他们分割成不同的小段。
#28
然后是反汇编出来的。
--- d:\documents\visual studio 2010\projects\调试5\调试5\调试5.cpp -------------------
1: #include <stdio.h>
2: #define MAXINT 20
3:
4: int bigplus(unsigned char a[],unsigned char b[],unsigned char c[]);
5:
6: int main(int argc, char *argv[])
7: {
00DB13A0 push ebp
00DB13A1 mov ebp,esp
00DB13A3 sub esp,158h
00DB13A9 push ebx
00DB13AA push esi
00DB13AB push edi
00DB13AC lea edi,[ebp-158h]
00DB13B2 mov ecx,56h
00DB13B7 mov eax,0CCCCCCCCh
00DB13BC rep stos dword ptr es:[edi]
00DB13BE mov eax,dword ptr [___security_cookie (0DB7000h)]
00DB13C3 xor eax,ebp
00DB13C5 mov dword ptr [ebp-4],eax
8: unsigned char a[MAXINT]={10,5,4,6,5,4,3,2,1,1,1}; //被乘数或被除数
00DB13C8 mov byte ptr [ebp-1Ch],0Ah
00DB13CC mov byte ptr [ebp-1Bh],5
00DB13D0 mov byte ptr [ebp-1Ah],4
00DB13D4 mov byte ptr [ebp-19h],6
00DB13D8 mov byte ptr [ebp-18h],5
00DB13DC mov byte ptr [ebp-17h],4
00DB13E0 mov byte ptr [ebp-16h],3
00DB13E4 mov byte ptr [ebp-15h],2
00DB13E8 mov byte ptr [ebp-14h],1
00DB13EC mov byte ptr [ebp-13h],1
00DB13F0 mov byte ptr [ebp-12h],1
00DB13F4 xor eax,eax
00DB13F6 mov dword ptr [ebp-11h],eax
00DB13F9 mov dword ptr [ebp-0Dh],eax
00DB13FC mov byte ptr [ebp-9],al
9: unsigned char b[MAXINT]={7,7,6,5,4,3,2,1}; //乘数或除数
00DB13FF mov byte ptr [ebp-38h],7
00DB1403 mov byte ptr [ebp-37h],7
00DB1407 mov byte ptr [ebp-36h],6
00DB140B mov byte ptr [ebp-35h],5
00DB140F mov byte ptr [ebp-34h],4
00DB1413 mov byte ptr [ebp-33h],3
00DB1417 mov byte ptr [ebp-32h],2
00DB141B mov byte ptr [ebp-31h],1
00DB141F xor eax,eax
00DB1421 mov dword ptr [ebp-30h],eax
00DB1424 mov dword ptr [ebp-2Ch],eax
00DB1427 mov dword ptr [ebp-28h],eax
10: unsigned char c[MAXINT],d[MAXINT]; //c[]存放商,d[]存放余数
11: int div=1234; //小乘数或小除数
00DB142A mov dword ptr [ebp-7Ch],4D2h
12: int k=0;
00DB1431 mov dword ptr [ebp-88h],0
13: int *res=&k; //小余数整数指针
00DB143B lea eax,[ebp-88h]
00DB1441 mov dword ptr [ebp-94h],eax
14: bigplus(a,b,c);
00DB1447 lea eax,[ebp-54h]
00DB144A push eax
00DB144B lea ecx,[ebp-38h]
00DB144E push ecx
00DB144F lea edx,[ebp-1Ch]
00DB1452 push edx
00DB1453 call bigplus (0DB11B8h)
00DB1458 add esp,0Ch
15:
16: getchar();
00DB145B mov esi,esp
00DB145D call dword ptr [__imp__getchar (0DB82B8h)]
00DB1463 cmp esi,esp
00DB1465 call @ILT+295(__RTC_CheckEsp) (0DB112Ch)
17: return 0;
00DB146A xor eax,eax
18: }
00DB146C push edx
00DB146D mov ecx,ebp
00DB146F push eax
00DB1470 lea edx,[ (0DB149Ch)]
00DB1476 call @ILT+120(@_RTC_CheckStackVars@8) (0DB107Dh)
00DB147B pop eax
00DB147C pop edx
00DB147D pop edi
00DB147E pop esi
00DB147F pop ebx
00DB1480 mov ecx,dword ptr [ebp-4]
00DB1483 xor ecx,ebp
00DB1485 call @ILT+15(@__security_check_cookie@4) (0DB1014h)
00DB148A add esp,158h
00DB1490 cmp ebp,esp
00DB1492 call @ILT+295(__RTC_CheckEsp) (0DB112Ch)
00DB1497 mov esp,ebp
00DB1499 pop ebp
00DB149A ret
00DB149B nop
00DB149C db 05h
00DB149D db 00h
00DB149E db 00h
00DB149F db 00h
00DB14A0 db a4h
00DB14A1 db 14h
00DB14A2 db dbh
00DB14A3 db 00h
00DB14A4 db e4h
00DB14A5 db ffh
00DB14A6 db ffh
00DB14A7 db ffh
00DB14A8 db 14h
00DB14A9 db 00h
00DB14AA db 00h
00DB14AB db 00h
00DB14AC db e8h
00DB14AD db 14h
00DB14AE db dbh
00DB14AF db 00h
00DB14B0 db c8h
00DB14B1 db ffh
00DB14B2 db ffh
00DB14B3 db ffh
00DB14B4 db 14h
00DB14B5 db 00h
00DB14B6 db 00h
00DB14B7 db 00h
00DB14B8 db e6h
00DB14B9 db 14h
00DB14BA db dbh
00DB14BB db 00h
00DB14BC db ach
00DB14BD db ffh
00DB14BE db ffh
00DB14BF db ffh
00DB14C0 db 14h
00DB14C1 db 00h
00DB14C2 db 00h
00DB14C3 db 00h
00DB14C4 db e4h
00DB14C5 db 14h
00DB14C6 db dbh
00DB14C7 db 00h
00DB14C8 db 90h
00DB14C9 db ffh
00DB14CA db ffh
00DB14CB db ffh
00DB14CC db 14h
00DB14CD db 00h
00DB14CE db 00h
00DB14CF db 00h
00DB14D0 db e2h
00DB14D1 db 14h
00DB14D2 db dbh
00DB14D3 db 00h
00DB14D4 db 78h
00DB14D5 db ffh
00DB14D6 db ffh
00DB14D7 db ffh
00DB14D8 db 04h
00DB14D9 db 00h
00DB14DA db 00h
00DB14DB db 00h
00DB14DC db e0h
00DB14DD db 14h
00DB14DE db dbh
00DB14DF db 00h
00DB14E0 db 6bh
00DB14E1 db 00h
00DB14E2 db 64h
00DB14E3 db 00h
00DB14E4 db 63h
00DB14E5 db 00h
00DB14E6 db 62h
00DB14E7 db 00h
00DB14E8 db 61h
00DB14E9 db 00h
--- 无源文件 -----------------------------------------------------------------------
00DB14EA int 3
00DB14EB int 3
00DB14EC int 3
00DB14ED int 3
00DB14EE int 3
00DB14EF int 3
00DB14F0 int 3
00DB14F1 int 3
00DB14F2 int 3
00DB14F3 int 3
00DB14F4 int 3
00DB14F5 int 3
00DB14F6 int 3
00DB14F7 int 3
00DB14F8 int 3
00DB14F9 int 3
00DB14FA int 3
00DB14FB int 3
00DB14FC int 3
00DB14FD int 3
00DB14FE int 3
00DB14FF int 3
00DB1500 int 3
00DB1501 int 3
00DB1502 int 3
00DB1503 int 3
00DB1504 int 3
00DB1505 int 3
00DB1506 int 3
00DB1507 int 3
00DB1508 int 3
00DB1509 int 3
00DB150A int 3
00DB150B int 3
00DB150C int 3
00DB150D int 3
00DB150E int 3
00DB150F int 3
00DB1510 int 3
00DB1511 int 3
00DB1512 int 3
00DB1513 int 3
00DB1514 int 3
00DB1515 int 3
00DB1516 int 3
00DB1517 int 3
00DB1518 int 3
00DB1519 int 3
00DB151A int 3
00DB151B int 3
00DB151C int 3
00DB151D int 3
00DB151E int 3
00DB151F int 3
00DB1520 int 3
00DB1521 int 3
00DB1522 int 3
00DB1523 int 3
00DB1524 int 3
00DB1525 int 3
00DB1526 int 3
00DB1527 int 3
00DB1528 int 3
00DB1529 int 3
00DB152A int 3
00DB152B int 3
00DB152C int 3
00DB152D int 3
00DB152E int 3
00DB152F int 3
00DB1530 int 3
00DB1531 int 3
00DB1532 int 3
00DB1533 int 3
00DB1534 int 3
00DB1535 int 3
00DB1536 int 3
00DB1537 int 3
00DB1538 int 3
00DB1539 int 3
00DB153A int 3
00DB153B int 3
00DB153C int 3
00DB153D int 3
00DB153E int 3
00DB153F int 3
#29
接着
--- d:\documents\visual studio 2010\projects\调试5\调试5\调试5.cpp -------------------
19:
20: int bigplus(unsigned char a[],unsigned char b[],unsigned char c[]) //大整数加法
21: {
00DB1540 push ebp
00DB1541 mov ebp,esp
00DB1543 sub esp,0DCh
00DB1549 push ebx
00DB154A push esi
00DB154B push edi
00DB154C lea edi,[ebp-0DCh]
00DB1552 mov ecx,37h
00DB1557 mov eax,0CCCCCCCCh
00DB155C rep stos dword ptr es:[edi]
22: int i,len;
23: len=(a[0]>b[0]?a[0]:b[0]); //a[0] b[0]保存数组长度,len为较长的一个
00DB155E mov eax,dword ptr [a]
00DB1561 movzx ecx,byte ptr [eax]
00DB1564 mov edx,dword ptr [b]
00DB1567 movzx eax,byte ptr [edx]
00DB156A cmp ecx,eax
00DB156C jle bigplus+3Bh (0DB157Bh)
00DB156E mov ecx,dword ptr [a]
00DB1571 mov dl,byte ptr [ecx]
00DB1573 mov byte ptr [ebp-0D9h],dl
00DB1579 jmp bigplus+46h (0DB1586h)
00DB157B mov eax,dword ptr [b]
00DB157E mov cl,byte ptr [eax]
00DB1580 mov byte ptr [ebp-0D9h],cl
00DB1586 movzx edx,byte ptr [ebp-0D9h]
00DB158D mov dword ptr [len],edx
24: for(i=0;i<MAXINT;i++) //将数组清0
00DB1590 mov dword ptr [i],0
00DB1597 jmp bigplus+62h (0DB15A2h)
00DB1599 mov eax,dword ptr [i]
00DB159C add eax,1
00DB159F mov dword ptr [i],eax
00DB15A2 cmp dword ptr [i],14h
00DB15A6 jge bigplus+73h (0DB15B3h)
25: c[i]=0;
00DB15A8 mov eax,dword ptr [c]
00DB15AB add eax,dword ptr [i]
00DB15AE mov byte ptr [eax],0
00DB15B1 jmp bigplus+59h (0DB1599h)
26: for (i=1;i<=len;i++) //计算每一位的值
00DB15B3 mov dword ptr [i],1
00DB15BA jmp bigplus+85h (0DB15C5h)
00DB15BC mov eax,dword ptr [i]
00DB15BF add eax,1
00DB15C2 mov dword ptr [i],eax
00DB15C5 mov eax,dword ptr [i]
00DB15C8 cmp eax,dword ptr [len]
00DB15CB jg bigplus+0EDh (0DB162Dh)
27: {
28: c[i]+=(a[i]+b[i]);
00DB15CD mov eax,dword ptr [a]
00DB15D0 add eax,dword ptr [i]
00DB15D3 movzx ecx,byte ptr [eax]
00DB15D6 mov edx,dword ptr [b]
00DB15D9 add edx,dword ptr [i]
00DB15DC movzx eax,byte ptr [edx]
00DB15DF add ecx,eax
00DB15E1 mov edx,dword ptr [c]
00DB15E4 add edx,dword ptr [i]
00DB15E7 movzx eax,byte ptr [edx]
00DB15EA add eax,ecx
00DB15EC mov ecx,dword ptr [c]
00DB15EF add ecx,dword ptr [i]
00DB15F2 mov byte ptr [ecx],al
29: if (c[i]>=10)
00DB15F4 mov eax,dword ptr [c]
00DB15F7 add eax,dword ptr [i]
00DB15FA movzx ecx,byte ptr [eax]
00DB15FD cmp ecx,0Ah
00DB1600 jl bigplus+0EBh (0DB162Bh)
30: {
31: c[i]-=10; //大于10的取个位
00DB1602 mov eax,dword ptr [c]
00DB1605 add eax,dword ptr [i]
00DB1608 movzx ecx,byte ptr [eax]
00DB160B sub ecx,0Ah
00DB160E mov edx,dword ptr [c]
00DB1611 add edx,dword ptr [i]
00DB1614 mov byte ptr [edx],cl
32: c[i+1]++; //高位加1
00DB1616 mov eax,dword ptr [c]
00DB1619 add eax,dword ptr [i]
00DB161C mov cl,byte ptr [eax+1]
00DB161F add cl,1
00DB1622 mov edx,dword ptr [c]
00DB1625 add edx,dword ptr [i]
00DB1628 mov byte ptr [edx+1],cl
33: }
34: }
00DB162B jmp bigplus+7Ch (0DB15BCh)
35: if (c[i+1]>0) len++;
00DB162D mov eax,dword ptr [c]
00DB1630 add eax,dword ptr [i]
00DB1633 movzx ecx,byte ptr [eax+1]
00DB1637 test ecx,ecx
00DB1639 jle bigplus+104h (0DB1644h)
00DB163B mov eax,dword ptr [len]
00DB163E add eax,1
00DB1641 mov dword ptr [len],eax
36: c[0]=len; //c[0]保存结果数组实际长度
00DB1644 mov eax,dword ptr [c]
00DB1647 mov cl,byte ptr [len]
00DB164A mov byte ptr [eax],cl
37: printf("Big integers add: ");
00DB164C mov esi,esp
00DB164E push offset string "Big integers add: " (0DB5744h)
00DB1653 call dword ptr [__imp__printf (0DB82B4h)]
00DB1659 add esp,4
00DB165C cmp esi,esp
00DB165E call @ILT+295(__RTC_CheckEsp) (0DB112Ch)
38: for (i=len;i>=1;i--)
00DB1663 mov eax,dword ptr [len]
00DB1666 mov dword ptr [i],eax
00DB1669 jmp bigplus+134h (0DB1674h)
00DB166B mov eax,dword ptr [i]
00DB166E sub eax,1
00DB1671 mov dword ptr [i],eax
00DB1674 cmp dword ptr [i],1
00DB1678 jl bigplus+15Dh (0DB169Dh)
39: printf("%d",c[i]); //打印结果
00DB167A mov eax,dword ptr [c]
00DB167D add eax,dword ptr [i]
00DB1680 movzx ecx,byte ptr [eax]
00DB1683 mov esi,esp
00DB1685 push ecx
00DB1686 push offset string "%d" (0DB5740h)
00DB168B call dword ptr [__imp__printf (0DB82B4h)]
00DB1691 add esp,8
00DB1694 cmp esi,esp
00DB1696 call @ILT+295(__RTC_CheckEsp) (0DB112Ch)
00DB169B jmp bigplus+12Bh (0DB166Bh)
40: printf("\n");
00DB169D mov esi,esp
00DB169F push offset string "\n" (0DB573Ch)
00DB16A4 call dword ptr [__imp__printf (0DB82B4h)]
00DB16AA add esp,4
00DB16AD cmp esi,esp
00DB16AF call @ILT+295(__RTC_CheckEsp) (0DB112Ch)
41: return 0;
00DB16B4 xor eax,eax
42: }
00DB16B6 pop edi
00DB16B7 pop esi
00DB16B8 pop ebx
00DB16B9 add esp,0DCh
00DB16BF cmp ebp,esp
00DB16C1 call @ILT+295(__RTC_CheckEsp) (0DB112Ch)
00DB16C6 mov esp,ebp
00DB16C8 pop ebp
00DB16C9 ret
#30
代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。
提醒:再牛×的老师也无法代替学生自己领悟和上厕所!
单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
提醒:再牛×的老师也无法代替学生自己领悟和上厕所!
单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
#31
最后是我嵌入C语言的代码。
因为原始的的反汇编代码,要跳转,而且跳转的位置还是直接用地址表示的。而我在编写的时候无法知道地址信息。所以一开始我是把相应的地址对应的行给标上一个名字,比如jmp jisuan。然后我把某一行前面标上jisuan:,然而,运行的结果是,貌似电脑无法识别这种标识。当然了,我记得在编写纯粹的汇编语言代码时是可以的,但是也许在C语言中是无法识别的。当然,没有报错,只是结果不对。
然后我把对应的跳转程序,分成一个个的小段,从这段跳转到另一段。结果是,程序不报错,但是结果不对。只有个位和十位正确,从百位开始就错了。往后更是都变成了0。
如果您忙的话,不用仔细看程序,跟我说说我是不是引用的格式(或者方式)不对啊。
#include<stdio.h>
# define MAXINT 20
int bigplus(unsigned char a[],unsigned char b[],unsigned char c[]);
int main(int argc, char *argv[])
{
unsigned char a[MAXINT]={10,0,9,8,7,6,5,4,3,2,1};
unsigned char b[MAXINT]={8,8,7,6,5,4,3,2,1};
unsigned char c[MAXINT],d[MAXINT]; //c[]存放商,d[]存放余数,g[]是除法时每次相乘的结果
bigplus(a,b,c);
return 0;
}
int bigplus(unsigned char a[],unsigned char b[],unsigned char c[])
{
int i,len;
len=(a[0]>b[0]?a[0]:b[0]); //a[0] b[0]保存数组长度,len为较长的一个
printf("len=%d\n",len);
for(i=0;i<MAXINT;i++) //将数组清0
{
c[i]=0;
}
__asm
{
mov dword ptr [i],1
jmp dian
}
dian:
__asm
{
mov eax,dword ptr [i]
cmp eax,dword ptr [len]
jg dian2
//c[i]+=(a[i]+b[i]);
mov eax,dword ptr [a]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax]
mov edx,dword ptr [b]
add edx,dword ptr [i]
movzx eax,byte ptr [edx]
add ecx,eax
mov edx,dword ptr [c]
add edx,dword ptr [i]
movzx eax,byte ptr [edx]
add eax,ecx
mov ecx,dword ptr [c]
add ecx,dword ptr [i]
mov byte ptr [ecx],al
// if (c[i]>=10)
mov eax,dword ptr [c]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax]
cmp ecx,0Ah
jl dian3 //小于10,跳转到开始循环位置
// c[i]-=10; //大于10的取个位
mov eax,dword ptr [c]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax]
sub ecx,0Ah
mov edx,dword ptr [c]
add edx,dword ptr [i]
mov byte ptr [edx],cl
// c[i+1]++; //高位加1
mov eax,dword ptr [c]
add eax,dword ptr [i]
mov cl,byte ptr [eax+1]
add cl,1
mov edx,dword ptr [c]
add edx,dword ptr [i]
mov byte ptr [edx+1],cl
// jmp bigplus+7Ch (13315BCh)
}
dian3:
__asm
{
mov eax,dword ptr [i]
add eax,1
mov dword ptr [i],eax
mov eax,dword ptr [i]
cmp eax,dword ptr [len]
jg dian2
//c[i]+=(a[i]+b[i]);
mov eax,dword ptr [a]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax]
mov edx,dword ptr [b]
add edx,dword ptr [i]
movzx eax,byte ptr [edx]
add ecx,eax
mov edx,dword ptr [c]
add edx,dword ptr [i]
movzx eax,byte ptr [edx]
add eax,ecx
mov ecx,dword ptr [c]
add ecx,dword ptr [i]
mov byte ptr [ecx],al
// if (c[i]>=10)
mov eax,dword ptr [c]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax]
cmp ecx,0Ah
jl dian3
// jl bg //小于10,跳转到开始循环位置
// c[i]-=10; //大于10的取个位
mov eax,dword ptr [c]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax]
sub ecx,0Ah
mov edx,dword ptr [c]
add edx,dword ptr [i]
mov byte ptr [edx],cl
// c[i+1]++; //高位加1
mov eax,dword ptr [c]
add eax,dword ptr [i]
mov cl,byte ptr [eax+1]
add cl,1
mov edx,dword ptr [c]
add edx,dword ptr [i]
mov byte ptr [edx+1],cl
// jmp bigplus+7Ch (13315BCh)
}
dian2:
__asm
{
mov eax,dword ptr [c]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax+1]
test ecx,ecx
jle dian4
mov eax,dword ptr [len]
add eax,1
mov dword ptr [len],eax
jmp dian4
}
// c[0]=len; //c[0]保存结果数组实际长度
dian4:
__asm
{
mov eax,dword ptr [c]
mov cl,byte ptr [len]
mov byte ptr [eax],cl
}
printf("Big integers add: ");
// printf("10进制:");
for (i=len;i>=1;i--)
{
printf("%d,",c[i]); //打印结果
}
printf("\n");
return 0;
}
因为原始的的反汇编代码,要跳转,而且跳转的位置还是直接用地址表示的。而我在编写的时候无法知道地址信息。所以一开始我是把相应的地址对应的行给标上一个名字,比如jmp jisuan。然后我把某一行前面标上jisuan:,然而,运行的结果是,貌似电脑无法识别这种标识。当然了,我记得在编写纯粹的汇编语言代码时是可以的,但是也许在C语言中是无法识别的。当然,没有报错,只是结果不对。
然后我把对应的跳转程序,分成一个个的小段,从这段跳转到另一段。结果是,程序不报错,但是结果不对。只有个位和十位正确,从百位开始就错了。往后更是都变成了0。
如果您忙的话,不用仔细看程序,跟我说说我是不是引用的格式(或者方式)不对啊。
#32
试试:
项目、属性、配置属性、C/C++、输出文件、汇编程序输出:程序集、机器码和源代码(/Facs)
在重新编译,查看生成的.asm文件内容。
项目、属性、配置属性、C/C++、输出文件、汇编程序输出:程序集、机器码和源代码(/Facs)
在重新编译,查看生成的.asm文件内容。
#33
再重新编译
#34
代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。
提醒:再牛×的老师也无法代替学生自己领悟和上厕所!
单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
#35
VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
#36
哈哈哈哈,嵌入成功了。感谢赵老师@赵4老师 ,感谢楼上各位的帮助。谢谢大家!!!!
#37
哈哈哈哈,嵌入成功了。感谢赵老师@赵4老师 ,感谢楼上各位的帮助。谢谢大家!!!!
小确幸!
#38
哈哈哈哈,嵌入成功了。感谢赵老师@赵4老师 ,感谢楼上各位的帮助。谢谢大家!!!!
一开始接手这个任务时,我信心满满,可是当自己着手开始做的时候,才发现,对于一个512位的数据,我怎么表示,这就成了第一大难关,如果不解决了,接下来的计算就无法进行。之后我试着位运算来计算加减乘除,可是,却不知道减法和乘法如何实现,更别提除法了。于是只好用C语言的算术运算来解决。被老师狠狠地批了一顿,并要求我必须用汇编或者位运算来完成计算过程。从此接近5天了,终于把汇编嵌入到了C语言中。虽然对开学之前完成整个工作抱有悲观看法,但是还是要继续努力做下去。总之要把它完成。
#39
老师也有老师对的地方和难处。
#40
老师也有老师对的地方和难处。
#41
恭喜,蹭点分
#42
恭喜,蹭点分
欢迎欢迎
#43
你只是源码级别的嵌入,我们可以考虑目标文件级别的嵌入。即汇编代码用汇编程序编译成目标文件,C语言代码用C编译器编译成目标文件,然后利用连接器链接这两个目标文件。
#1
作为一个新手,别人的程序都不会用。真悲哀啊。
#2
这种代码,别嵌入了,直接汇编就可以了
VC++ 内部有汇编器,可以直接用
如果嫌麻烦,可以到网上下载
masm32 //32BitsWindows,以及16Bits Dos 汇编器
masm615 //masm 6.15 版本。
VC++ 内部有汇编器,可以直接用
如果嫌麻烦,可以到网上下载
masm32 //32BitsWindows,以及16Bits Dos 汇编器
masm615 //masm 6.15 版本。
#3
这种代码,别嵌入了,直接汇编就可以了
VC++ 内部有汇编器,可以直接用
如果嫌麻烦,可以到网上下载
masm32 //32BitsWindows,以及16Bits Dos 汇编器
masm615 //masm 6.15 版本。
#4
直接在控制台 命令行输入 ml a.asm 就可以了
ml /? 可以得到帮助信息
ml /? 可以得到帮助信息
#5
在BC31下嵌入16位汇编
在VC下嵌入32位汇编
在VC下嵌入32位汇编
#6
#7
以下内容摘自bc++3.1 asm联机帮助:
asm, _asm, __asm (keywords)
You use the asm statements to place assembly language statements in the
middle of your C++ source code.
Syntax:
asm <opcode> <operands> <; or newline>
_asm <opcode> <operands> <; or newline>
__asm <opcode> <operands> <; or newline>
Any C++ symbols are replaced by the appropriate assembly language
equivalents.
If you want to include a number of asm statements, surround them with
braces:
asm {
pop ax; pop ds
iret
}
Example
asm mov ax,_stklen
See Also:
BASM
asm, _asm, __asm (keywords)
You use the asm statements to place assembly language statements in the
middle of your C++ source code.
Syntax:
asm <opcode> <operands> <; or newline>
_asm <opcode> <operands> <; or newline>
__asm <opcode> <operands> <; or newline>
Any C++ symbols are replaced by the appropriate assembly language
equivalents.
If you want to include a number of asm statements, surround them with
braces:
asm {
pop ax; pop ds
iret
}
Example
asm mov ax,_stklen
See Also:
BASM
#8
没见过把完整的汇编语言源程序嵌进去的
#9
不是所有汇编指令都支持
#10
之前我根本不知道c语言的程序里面能嵌入汇编,那天老师说可以,我才知道。具体如何嵌入让我自己去搜
#11
主观能动性还是要发挥的。
#12
内联汇编仅限汇编指令
那些汇编器定义的宏, 像 SEGMENT, DB, DW 之类的是不支持的. 可以用 _emit 指令可以代替 db 之类的宏.
在内联汇编里面可以直接访问 C/C++ 里面的变量和函数, 很多时候还是比独立汇编方便.
那些汇编器定义的宏, 像 SEGMENT, DB, DW 之类的是不支持的. 可以用 _emit 指令可以代替 db 之类的宏.
在内联汇编里面可以直接访问 C/C++ 里面的变量和函数, 很多时候还是比独立汇编方便.
#13
仅供参考:
#pragma option -N-
//-------------------------------------------------------
#include <conio.h>
#include <dos.h>
#include <stdio.h>
//-------------------------------------------------------
#define YES 1
#define NO 0
#define CURSOR_MOVE 1
#define LEFT_DOWN 2
#define LEFT_UP 4
#define RIGHT_DOWN 8
#define RIGHT_UP 16
int MouseActive=NO,MouseMask,MouseButton,MouseX,MouseY;
//-------------------------------------------------------
void far mscall()
{
asm {
push ds
push si
xor si,si
mov ds,si
mov si,[0x40E]
mov ds,si
cmp ax,MouseMask
jne changed
cmp bx,MouseButton
jne changed
cmp cx,MouseX
jne changed
cmp dx,MouseY
je nochange
}
changed:
asm {
mov MouseMask,ax
mov MouseButton,bx
mov MouseX,cx
mov MouseY,dx
mov MouseActive,YES
jmp end
}
nochange:
asm {
mov MouseActive,NO
}
end:
asm {
pop si
pop ds
}
}
//-------------------------------------------------------
void MsLinkUserCall()
{
union REGS r;
struct SREGS sr;
*((int *)(0x0000040E))=FP_SEG(&MouseActive);
r.x.ax=0x0C;
r.x.cx=0x001F;
r.x.dx=FP_OFF(mscall);
sr.es=FP_SEG(mscall);
int86x(0x33,&r,&r,&sr);
}
//-------------------------------------------------------
int MsInstall()
{
void far *address;
union REGS regs;
address=getvect(0x33);
if((address==NULL)||(*(unsigned char *)address==0xCF)) return 0;
else {
regs.x.ax=0;
int86(0x33,®s,®s);
return regs.x.ax;
}
}
//-------------------------------------------------------
void MsShow()
{
union REGS regs;
regs.x.ax=1;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void MsHide()
{
union REGS regs;
regs.x.ax=2;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void MsSetLoc(x,y)
unsigned int x,y;
{
union REGS regs;
regs.x.ax=4;
regs.x.cx=x;
regs.x.dx=y;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void MsSetHoriLimit(l,r)
unsigned int l,r;
{
union REGS regs;
regs.x.ax=7;
regs.x.cx=l;
regs.x.dx=r;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void MsSetVertLimit(t,b)
unsigned int t,b;
{
union REGS regs;
regs.x.ax=8;
regs.x.cx=t;
regs.x.dx=b;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void main()
{
if (!MsInstall()) {
printf("I need a mouse.\n");
return;
}
clrscr();
MsLinkUserCall();
MsSetHoriLimit(0,638);
MsSetVertLimit(0,192);
MsSetLoc(0,0);
MsShow();
while (1) {
if (kbhit()) {
if (getch()==27) break;
}
if (MouseActive==YES) {
if (MouseMask&LEFT_DOWN) {
MsHide();printf(" LEFT_DOWN");MsShow();
}
if (MouseMask&LEFT_UP) {
MsHide();printf(" LEFT_UP");MsShow();
}
if (MouseMask&RIGHT_DOWN) {
MsHide();printf(" RIGHT_DOWN");MsShow();
}
if (MouseMask&RIGHT_UP) {
MsHide();printf(" RIGHT_UP");MsShow();
}
if (MouseButton&1) {
MsHide();printf(" LEFT_DRAG");MsShow();
}
if (MouseButton&2) {
MsHide();printf(" RIGHT_DRAG");MsShow();
}
if (MouseMask&CURSOR_MOVE) {
MsHide();printf(" MOVE_TO(%3d,%3d)",MouseX,MouseY);MsShow();
}
MsHide();printf("\n");MsShow();
MouseActive=NO;
}
}
MsHide();
MsInstall();
}
#14
VC++早就不支持生成16位程序,不论dos16、win16,你嵌入的是dos 16位汇编,根本不可能通过,而且还有一部分MASM语法在嵌入汇编中不支持。
#15
仅供参考:#pragma option -N-
//-------------------------------------------------------
#include <conio.h>
#include <dos.h>
#include <stdio.h>
//-------------------------------------------------------
#define YES 1
#define NO 0
#define CURSOR_MOVE 1
#define LEFT_DOWN 2
#define LEFT_UP 4
#define RIGHT_DOWN 8
#define RIGHT_UP 16
int MouseActive=NO,MouseMask,MouseButton,MouseX,MouseY;
//-------------------------------------------------------
void far mscall()
{
asm {
push ds
push si
xor si,si
mov ds,si
mov si,[0x40E]
mov ds,si
cmp ax,MouseMask
jne changed
cmp bx,MouseButton
jne changed
cmp cx,MouseX
jne changed
cmp dx,MouseY
je nochange
}
changed:
asm {
mov MouseMask,ax
mov MouseButton,bx
mov MouseX,cx
mov MouseY,dx
mov MouseActive,YES
jmp end
}
nochange:
asm {
mov MouseActive,NO
}
end:
asm {
pop si
pop ds
}
}
//-------------------------------------------------------
void MsLinkUserCall()
{
union REGS r;
struct SREGS sr;
*((int *)(0x0000040E))=FP_SEG(&MouseActive);
r.x.ax=0x0C;
r.x.cx=0x001F;
r.x.dx=FP_OFF(mscall);
sr.es=FP_SEG(mscall);
int86x(0x33,&r,&r,&sr);
}
//-------------------------------------------------------
int MsInstall()
{
void far *address;
union REGS regs;
address=getvect(0x33);
if((address==NULL)||(*(unsigned char *)address==0xCF)) return 0;
else {
regs.x.ax=0;
int86(0x33,®s,®s);
return regs.x.ax;
}
}
//-------------------------------------------------------
void MsShow()
{
union REGS regs;
regs.x.ax=1;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void MsHide()
{
union REGS regs;
regs.x.ax=2;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void MsSetLoc(x,y)
unsigned int x,y;
{
union REGS regs;
regs.x.ax=4;
regs.x.cx=x;
regs.x.dx=y;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void MsSetHoriLimit(l,r)
unsigned int l,r;
{
union REGS regs;
regs.x.ax=7;
regs.x.cx=l;
regs.x.dx=r;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void MsSetVertLimit(t,b)
unsigned int t,b;
{
union REGS regs;
regs.x.ax=8;
regs.x.cx=t;
regs.x.dx=b;
int86(0x33,®s,®s);
}
//-------------------------------------------------------
void main()
{
if (!MsInstall()) {
printf("I need a mouse.\n");
return;
}
clrscr();
MsLinkUserCall();
MsSetHoriLimit(0,638);
MsSetVertLimit(0,192);
MsSetLoc(0,0);
MsShow();
while (1) {
if (kbhit()) {
if (getch()==27) break;
}
if (MouseActive==YES) {
if (MouseMask&LEFT_DOWN) {
MsHide();printf(" LEFT_DOWN");MsShow();
}
if (MouseMask&LEFT_UP) {
MsHide();printf(" LEFT_UP");MsShow();
}
if (MouseMask&RIGHT_DOWN) {
MsHide();printf(" RIGHT_DOWN");MsShow();
}
if (MouseMask&RIGHT_UP) {
MsHide();printf(" RIGHT_UP");MsShow();
}
if (MouseButton&1) {
MsHide();printf(" LEFT_DRAG");MsShow();
}
if (MouseButton&2) {
MsHide();printf(" RIGHT_DRAG");MsShow();
}
if (MouseMask&CURSOR_MOVE) {
MsHide();printf(" MOVE_TO(%3d,%3d)",MouseX,MouseY);MsShow();
}
MsHide();printf("\n");MsShow();
MouseActive=NO;
}
}
MsHide();
MsInstall();
}
#16
D:\BC\flc>dir mouse*.c
驱动器 D 中的卷是 Q_HD2_8
卷的序列号是 54FC-A4FD
D:\BC\flc 的目录
1998-03-31 14:55 3,428 MOUSETST.C
1 个文件 3,428 字节
0 个目录 16,783,536,128 可用字节
D:\BC\flc>
驱动器 D 中的卷是 Q_HD2_8
卷的序列号是 54FC-A4FD
D:\BC\flc 的目录
1998-03-31 14:55 3,428 MOUSETST.C
1 个文件 3,428 字节
0 个目录 16,783,536,128 可用字节
D:\BC\flc>
#17
提醒:
Win7下需要在DosBox中运行BC++3.1或TC
WinXP下,建一个批处理bc.bat,内容为下面两行,放在bc.exe同目录下,再将bc.bat发送到桌面快捷方式:
del tc*.swp >NUL
start command /c bc.exe
如果想在IDE里面使用鼠标,还应将快捷方式属性中的快速编辑模式关掉。
Win7下需要在DosBox中运行BC++3.1或TC
WinXP下,建一个批处理bc.bat,内容为下面两行,放在bc.exe同目录下,再将bc.bat发送到桌面快捷方式:
del tc*.swp >NUL
start command /c bc.exe
如果想在IDE里面使用鼠标,还应将快捷方式属性中的快速编辑模式关掉。
#18
提醒:
Win7下需要在DosBox中运行BC++3.1或TC
WinXP下,建一个批处理bc.bat,内容为下面两行,放在bc.exe同目录下,再将bc.bat发送到桌面快捷方式:
del tc*.swp >NUL
start command /c bc.exe
如果想在IDE里面使用鼠标,还应将快捷方式属性中的快速编辑模式关掉。
#19
啊,赵老师,你说的我不太懂。嗯,首先你这个程序我只是看了他的结构,如何在C语言中整段的定义使用汇编语言的。对于程序的内容我没有细看,刚才你一说与鼠标相关的话题,我没听懂。你这个程序是讲如何在BC下使用鼠标吗?可是我记得BC下本来就可以使用鼠标啊。
提醒:
Win7下需要在DosBox中运行BC++3.1或TC
WinXP下,建一个批处理bc.bat,内容为下面两行,放在bc.exe同目录下,再将bc.bat发送到桌面快捷方式:
del tc*.swp >NUL
start command /c bc.exe
如果想在IDE里面使用鼠标,还应将快捷方式属性中的快速编辑模式关掉。
我是担心你在比如Win7下或Win7 64位下用不了BC
#20
啊,赵老师,你说的我不太懂。嗯,首先你这个程序我只是看了他的结构,如何在C语言中整段的定义使用汇编语言的。对于程序的内容我没有细看,刚才你一说与鼠标相关的话题,我没听懂。你这个程序是讲如何在BC下使用鼠标吗?可是我记得BC下本来就可以使用鼠标啊。
提醒:
Win7下需要在DosBox中运行BC++3.1或TC
WinXP下,建一个批处理bc.bat,内容为下面两行,放在bc.exe同目录下,再将bc.bat发送到桌面快捷方式:
del tc*.swp >NUL
start command /c bc.exe
如果想在IDE里面使用鼠标,还应将快捷方式属性中的快速编辑模式关掉。
我是担心你在比如Win7下或Win7 64位下用不了BC
啊,赵老师,你说的我不太懂。嗯,首先你这个程序我只是看了他的结构,如何在C语言中整段的定义使用汇编语言的。对于程序的内容我没有细看,刚才你一说与鼠标相关的话题,我没听懂。你这个程序是讲如何在BC下使用鼠标吗?可是我记得BC下本来就可以使用鼠标啊。
提醒:
Win7下需要在DosBox中运行BC++3.1或TC
WinXP下,建一个批处理bc.bat,内容为下面两行,放在bc.exe同目录下,再将bc.bat发送到桌面快捷方式:
del tc*.swp >NUL
start command /c bc.exe
如果想在IDE里面使用鼠标,还应将快捷方式属性中的快速编辑模式关掉。
我是担心你在比如Win7下或Win7 64位下用不了BC
#21
VS2010只能嵌入32位汇编,嵌入不了16位或64位汇编。
32位汇编参考下面:
32位汇编参考下面:
X86和X87汇编指令大全(有注释)
---------- 一、数据传输指令 ----------------------------------------------------
它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.
1. 通用数据传送指令.
MOV 传送字或字节.
MOVSX 先符号扩展,再传送.
MOVZX 先零扩展,再传送.
PUSH 把字压入堆栈.
POP 把字弹出堆栈.
PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.
POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.
PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.
POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.
BSWAP 交换32位寄存器里字节的顺序
XCHG 交换字或字节.(至少有一个操作数为寄存器,段寄存器不可作为操作数)
CMPXCHG 比较并交换操作数.(第二个操作数必须为累加器AL/AX/EAX)
XADD 先交换再累加.(结果在第一个操作数里)
XLAT 字节查表转换.----BX指向一张256字节的表的起点,AL为表的索引值(0-255,即0-FFH);返回AL为查表结果.([BX+AL]->AL)
2. 输入输出端口传送指令.
IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )
OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器 )输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时,其范围是 0-65535.
3. 目的地址传送指令.
LEA 装入有效地址.例: LEA DX,string ;把偏移地址存到DX.
LDS 传送目标指针,把指针内容装入DS.例: LDS SI,string ;把段地址:偏移地址存到DS:SI.
LES 传送目标指针,把指针内容装入ES.例: LES DI,string ;把段地址:偏移地址存到ES:DI.
LFS 传送目标指针,把指针内容装入FS.例: LFS DI,string ;把段地址:偏移地址存到FS:DI.
LGS 传送目标指针,把指针内容装入GS.例: LGS DI,string ;把段地址:偏移地址存到GS:DI.
LSS 传送目标指针,把指针内容装入SS.例: LSS DI,string ;把段地址:偏移地址存到SS:DI.
4. 标志传送指令.
LAHF 标志寄存器传送,把标志装入AH.
SAHF 标志寄存器传送,把AH内容装入标志寄存器.
PUSHF 标志入栈.
POPF 标志出栈.
PUSHD 32位标志入栈.
POPD 32位标志出栈.
---------- 二、算术运算指令 ----------------------------------------------------
ADD 加法.
ADC 带进位加法.
INC 加 1.
AAA 加法的ASCII码调整.
DAA 加法的十进制调整.
SUB 减法.
SBB 带借位减法.
DEC 减 1.
NEG 求反(以 0 减之).
CMP 比较.(两操作数作减法,仅修改标志位,不回送结果).
AAS 减法的ASCII码调整.
DAS 减法的十进制调整.
MUL 无符号乘法.结果回送AH和AL(字节运算),或DX和AX(字运算),
IMUL 整数乘法.结果回送AH和AL(字节运算),或DX和AX(字运算),
AAM 乘法的ASCII码调整.
DIV 无符号除法.结果回送:商回送AL,余数回送AH, (字节运算);或 商回送AX,余数回送DX, (字运算).
IDIV 整数除法.结果回送:商回送AL,余数回送AH, (字节运算);或 商回送AX,余数回送DX, (字运算).
AAD 除法的ASCII码调整.
CBW 字节转换为字. (把AL中字节的符号扩展到AH中去)
CWD 字转换为双字. (把AX中的字的符号扩展到DX中去)
CWDE 字转换为双字. (把AX中的字符号扩展到EAX中去)
CDQ 双字扩展. (把EAX中的字的符号扩展到EDX中去)
---------- 三、逻辑运算指令 ----------------------------------------------------
AND 与运算.
OR 或运算.
XOR 异或运算.
NOT 取反.
TEST 测试.(两操作数作与运算,仅修改标志位,不回送结果).
SHL 逻辑左移.
SAL 算术左移.(=SHL)
SHR 逻辑右移.
SAR 算术右移.(=SHR)
ROL 循环左移.
ROR 循环右移.
RCL 通过进位的循环左移.
RCR 通过进位的循环右移.
以上八种移位指令,其移位次数可达255次.
移位一次时, 可直接用操作码. 如 SHL AX,1.
移位>1次时, 则由寄存器CL给出移位次数.
如 MOV CL,04 SHL AX,CL
---------- 四、串指令 ----------------------------------------------------------
DS:SI 源串段寄存器 :源串变址.
ES:DI 目标串段寄存器:目标串变址.
CX 重复次数计数器.
AL/AX 扫描值.
D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量.
Z标志 用来控制扫描或比较操作的结束.
MOVS 串传送.( MOVSB 传送字符. MOVSW 传送字. MOVSD 传送双字. )
CMPS 串比较.( CMPSB 比较字符. CMPSW 比较字. )
SCAS 串扫描.把AL或AX的内容与目标串作比较,比较结果反映在标志位.
LODS 装入串.把源串中的元素(字或字节)逐一装入AL或AX中.( LODSB 传送字符. LODSW 传送字. LODSD 传送双字. )
STOS 保存串.是LODS的逆过程.
REP 当CX/ECX<>0时重复.
REPE/REPZ 当ZF=1或比较结果相等,且CX/ECX<>0时重复.
REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复.
REPC 当CF=1且CX/ECX<>0时重复.
REPNC 当CF=0且CX/ECX<>0时重复.
---------- 五、程序转移指令 ----------------------------------------------------
1. 无条件转移指令 (长转移)
JMP 无条件转移指令
CALL 过程调用
RET/RETF 过程返回.
2. 条件转移指令 (短转移,-128到+127的距离内)( 当且仅当(SF XOR OF)=1时,OP1<OP2 )
JA/JNBE 不小于或不等于时转移.
JAE/JNB 大于或等于转移.
JB/JNAE 小于转移.
JBE/JNA 小于或等于转移.
以上四条,测试无符号整数运算的结果(标志C和Z).
JG/JNLE 大于转移.
JGE/JNL 大于或等于转移.
JL/JNGE 小于转移.
JLE/JNG 小于或等于转移.
以上四条,测试带符号整数运算的结果(标志S,O和Z).
JE/JZ 等于转移.
JNE/JNZ 不等于时转移.
JC 有进位时转移.
JNC 无进位时转移.
JNO 不溢出时转移.
JNP/JPO 奇偶性为奇数时转移.
JNS 符号位为 "0" 时转移.
JO 溢出转移.
JP/JPE 奇偶性为偶数时转移.
JS 符号位为 "1" 时转移.
3. 循环控制指令(短转移)
LOOP CX不为零时循环.
LOOPE/LOOPZ CX不为零且标志Z=1时循环.
LOOPNE/LOOPNZ CX不为零且标志Z=0时循环.
JCXZ CX为零时转移.
JECXZ ECX为零时转移.
4. 中断指令
INT 中断指令
INTO 溢出中断
IRET 中断返回
5. 处理器控制指令
HLT 处理器暂停, 直到出现中断或复位信号才继续.
WAIT 当芯片引线TEST为高电平时使CPU进入等待状态.
ESC 转换到外处理器.
LOCK *总线.
NOP 空操作.
STC 置进位标志位.
CLC 清进位标志位.
CMC 进位标志取反.
STD 置方向标志位.
CLD 清方向标志位.
STI 置中断允许位.
CLI 清中断允许位.
---------- 六、伪指令 ----------------------------------------------------------
DW 定义字(2字节).
PROC 定义过程.
ENDP 过程结束.
SEGMENT 定义段.
ASSUME 建立段寄存器寻址.
ENDS 段结束.
END 程序结束.
---------- 七、处理机控制指令:标志处理指令 ------------------------------------
CLC 进位位置0指令
CMC 进位位求反指令
STC 进位位置为1指令
CLD 方向标志置1指令
STD 方向标志位置1指令
CLI 中断标志置0指令
STI 中断标志置1指令
NOP 无操作
HLT 停机
WAIT 等待
ESC 换码
LOCK *
========== 浮点运算指令集 ======================================================
---------- 一、控制指令(带9B的控制指令前缀F变为FN时浮点不检查,机器码去掉9B)----
FINIT 初始化浮点部件 机器码 9B DB E3
FCLEX 清除异常 机器码 9B DB E2
FDISI 浮点检查禁止中断 机器码 9B DB E1
FENI 浮点检查禁止中断二 机器码 9B DB E0
WAIT 同步CPU和FPU 机器码 9B
FWAIT 同步CPU和FPU 机器码 D9 D0
FNOP 无操作 机器码 DA E9
FXCH 交换ST(0)和ST(1) 机器码 D9 C9
FXCH ST(i) 交换ST(0)和ST(i) 机器码 D9 C1iii
FSTSW ax 状态字到ax 机器码 9B DF E0
FSTSW word ptr mem 状态字到mem 机器码 9B DD mm111mmm
FLDCW word ptr mem mem到状态字 机器码 D9 mm101mmm
FSTCW word ptr mem 控制字到mem 机器码 9B D9 mm111mmm
FLDENV word ptr mem mem到全环境 机器码 D9 mm100mmm
FSTENV word ptr mem 全环境到mem 机器码 9B D9 mm110mmm
FRSTOR word ptr mem mem到FPU状态 机器码 DD mm100mmm
FSAVE word ptr mem FPU状态到mem 机器码 9B DD mm110mmm
FFREE ST(i) 标志ST(i)未使用 机器码 DD C0iii
FDECSTP 减少栈指针1->0 2->1 机器码 D9 F6
FINCSTP 增加栈指针0->1 1->2 机器码 D9 F7
FSETPM 浮点设置保护 机器码 DB E4
---------- 二、数据传送指令 ----------------------------------------------------
FLDZ 将0.0装入ST(0) 机器码 D9 EE
FLD1 将1.0装入ST(0) 机器码 D9 E8
FLDPI 将π装入ST(0) 机器码 D9 EB
FLDL2T 将ln10/ln2装入ST(0) 机器码 D9 E9
FLDL2E 将1/ln2装入ST(0) 机器码 D9 EA
FLDLG2 将ln2/ln10装入ST(0) 机器码 D9 EC
FLDLN2 将ln2装入ST(0) 机器码 D9 ED
FLD real4 ptr mem 装入mem的单精度浮点数 机器码 D9 mm000mmm
FLD real8 ptr mem 装入mem的双精度浮点数 机器码 DD mm000mmm
FLD real10 ptr mem 装入mem的十字节浮点数 机器码 DB mm101mmm
FILD word ptr mem 装入mem的二字节整数 机器码 DF mm000mmm
FILD dword ptr mem 装入mem的四字节整数 机器码 DB mm000mmm
FILD qword ptr mem 装入mem的八字节整数 机器码 DF mm101mmm
FBLD tbyte ptr mem 装入mem的十字节BCD数 机器码 DF mm100mmm
FST real4 ptr mem 保存单精度浮点数到mem 机器码 D9 mm010mmm
FST real8 ptr mem 保存双精度浮点数到mem 机器码 DD mm010mmm
FIST word ptr mem 保存二字节整数到mem 机器码 DF mm010mmm
FIST dword ptr mem 保存四字节整数到mem 机器码 DB mm010mmm
FSTP real4 ptr mem 保存单精度浮点数到mem并出栈 机器码 D9 mm011mmm
FSTP real8 ptr mem 保存双精度浮点数到mem并出栈 机器码 DD mm011mmm
FSTP real10 ptr mem 保存十字节浮点数到mem并出栈 机器码 DB mm111mmm
FISTP word ptr mem 保存二字节整数到mem并出栈 机器码 DF mm011mmm
FISTP dword ptr mem 保存四字节整数到mem并出栈 机器码 DB mm011mmm
FISTP qword ptr mem 保存八字节整数到mem并出栈 机器码 DF mm111mmm
FBSTP tbyte ptr mem 保存十字节BCD数到mem并出栈 机器码 DF mm110mmm
FCMOVB ST(0),ST(i) <时传送 机器码 DA C0iii
FCMOVBE ST(0),ST(i) <=时传送 机器码 DA D0iii
FCMOVE ST(0),ST(i) =时传送 机器码 DA C1iii
FCMOVNB ST(0),ST(i) >=时传送 机器码 DB C0iii
FCMOVNBE ST(0),ST(i) >时传送 机器码 DB D0iii
FCMOVNE ST(0),ST(i) !=时传送 机器码 DB C1iii
FCMOVNU ST(0),ST(i) 有序时传送 机器码 DB D1iii
FCMOVU ST(0),ST(i) 无序时传送 机器码 DA D1iii
---------- 三、比较指令 --------------------------------------------------------
FCOM ST(0)-ST(1) 机器码 D8 D1
FCOMI ST(0),ST(i) ST(0)-ST(1) 机器码 DB F0iii
FCOMIP ST(0),ST(i) ST(0)-ST(1)并出栈 机器码 DF F0iii
FCOM real4 ptr mem ST(0)-实数mem 机器码 D8 mm010mmm
FCOM real8 ptr mem ST(0)-实数mem 机器码 DC mm010mmm
FICOM word ptr mem ST(0)-整数mem 机器码 DE mm010mmm
FICOM dword ptr mem ST(0)-整数mem 机器码 DA mm010mmm
FICOMP word ptr mem ST(0)-整数mem并出栈 机器码 DE mm011mmm
FICOMP dword ptr mem ST(0)-整数mem并出栈 机器码 DA mm011mmm
FTST ST(0)-0 机器码 D9 E4
FUCOM ST(i) ST(0)-ST(i) 机器码 DD E0iii
FUCOMP ST(i) ST(0)-ST(i)并出栈 机器码 DD E1iii
FUCOMPP ST(0)-ST(1)并二次出栈 机器码 DA E9
FXAM ST(0)规格类型 机器码 D9 E5
---------- 四、运算指令 --------------------------------------------------------
FADD 把目的操作数 (直接接在指令后的变量或堆栈缓存器) 与来源操作数 (接在目的操作数后的变量或堆栈缓存器) 相加,并将结果存入目的操作数
FADDP ST(i),ST 这个指令是使目的操作数加上 ST 缓存器,并弹出 ST 缓存器,而目的操作数必须是堆栈缓存器的其中之一,最后不管目的操作数为何,经弹出一次后,目的操作数会变成上一个堆栈缓存器了
FIADD FIADD 是把 ST 加上来源操作数,然后再存入 ST 缓存器,来源操作数必须是字组整数或短整数形态的变数
FSUB 减
FSUBP
FSUBR 减数与被减数互换
FSUBRP
FISUB
FISUBR
FMUL 乘
FMULP
FIMUL
FDIV 除
FDIVP
FDIVR
FDIVRP
FIDIV
FIDIVR
FCHS 改变 ST 的正负值
FABS 把 ST 之值取出,取其绝对值后再存回去。
FSQRT 将 ST 之值取出,开根号后再存回去。
FSCALE 这个指令是计算 ST*2^ST(1)之值,再把结果存入 ST 里而 ST(1) 之值不变。ST(1) 必须是在 -32768 到 32768 (-215 到 215 )之间的整数,如果超过这个范围计算结果无法确定,如果不是整数 ST(1) 会先向零舍入成整数再计算。所以为安全起见,最好是由字组整数载入到 ST(1) 里。
FRNDINT 这个指令是把 ST 的数值舍入成整数,FPU 提供四种舍入方式,由 FPU 的控制字组(control word)中的 RC 两个位决定
RC 舍入控制
00 四舍五入
01 向负无限大舍入
10 向正无限大舍入
11 向零舍去
================================================================================
#22
VS2010只能嵌入32位汇编,嵌入不了16位或64位汇编。
32位汇编参考下面:X86和X87汇编指令大全(有注释)
---------- 一、数据传输指令 ----------------------------------------------------
它们在存贮器和寄存器、寄存器和输入输出端口之间传送数据.
1. 通用数据传送指令.
MOV 传送字或字节.
MOVSX 先符号扩展,再传送.
MOVZX 先零扩展,再传送.
PUSH 把字压入堆栈.
POP 把字弹出堆栈.
PUSHA 把AX,CX,DX,BX,SP,BP,SI,DI依次压入堆栈.
POPA 把DI,SI,BP,SP,BX,DX,CX,AX依次弹出堆栈.
PUSHAD 把EAX,ECX,EDX,EBX,ESP,EBP,ESI,EDI依次压入堆栈.
POPAD 把EDI,ESI,EBP,ESP,EBX,EDX,ECX,EAX依次弹出堆栈.
BSWAP 交换32位寄存器里字节的顺序
XCHG 交换字或字节.(至少有一个操作数为寄存器,段寄存器不可作为操作数)
CMPXCHG 比较并交换操作数.(第二个操作数必须为累加器AL/AX/EAX)
XADD 先交换再累加.(结果在第一个操作数里)
XLAT 字节查表转换.----BX指向一张256字节的表的起点,AL为表的索引值(0-255,即0-FFH);返回AL为查表结果.([BX+AL]->AL)
2. 输入输出端口传送指令.
IN I/O端口输入. ( 语法: IN 累加器, {端口号│DX} )
OUT I/O端口输出. ( 语法: OUT {端口号│DX},累加器 )输入输出端口由立即方式指定时, 其范围是 0-255; 由寄存器 DX 指定时,其范围是 0-65535.
3. 目的地址传送指令.
LEA 装入有效地址.例: LEA DX,string ;把偏移地址存到DX.
LDS 传送目标指针,把指针内容装入DS.例: LDS SI,string ;把段地址:偏移地址存到DS:SI.
LES 传送目标指针,把指针内容装入ES.例: LES DI,string ;把段地址:偏移地址存到ES:DI.
LFS 传送目标指针,把指针内容装入FS.例: LFS DI,string ;把段地址:偏移地址存到FS:DI.
LGS 传送目标指针,把指针内容装入GS.例: LGS DI,string ;把段地址:偏移地址存到GS:DI.
LSS 传送目标指针,把指针内容装入SS.例: LSS DI,string ;把段地址:偏移地址存到SS:DI.
4. 标志传送指令.
LAHF 标志寄存器传送,把标志装入AH.
SAHF 标志寄存器传送,把AH内容装入标志寄存器.
PUSHF 标志入栈.
POPF 标志出栈.
PUSHD 32位标志入栈.
POPD 32位标志出栈.
---------- 二、算术运算指令 ----------------------------------------------------
ADD 加法.
ADC 带进位加法.
INC 加 1.
AAA 加法的ASCII码调整.
DAA 加法的十进制调整.
SUB 减法.
SBB 带借位减法.
DEC 减 1.
NEG 求反(以 0 减之).
CMP 比较.(两操作数作减法,仅修改标志位,不回送结果).
AAS 减法的ASCII码调整.
DAS 减法的十进制调整.
MUL 无符号乘法.结果回送AH和AL(字节运算),或DX和AX(字运算),
IMUL 整数乘法.结果回送AH和AL(字节运算),或DX和AX(字运算),
AAM 乘法的ASCII码调整.
DIV 无符号除法.结果回送:商回送AL,余数回送AH, (字节运算);或 商回送AX,余数回送DX, (字运算).
IDIV 整数除法.结果回送:商回送AL,余数回送AH, (字节运算);或 商回送AX,余数回送DX, (字运算).
AAD 除法的ASCII码调整.
CBW 字节转换为字. (把AL中字节的符号扩展到AH中去)
CWD 字转换为双字. (把AX中的字的符号扩展到DX中去)
CWDE 字转换为双字. (把AX中的字符号扩展到EAX中去)
CDQ 双字扩展. (把EAX中的字的符号扩展到EDX中去)
---------- 三、逻辑运算指令 ----------------------------------------------------
AND 与运算.
OR 或运算.
XOR 异或运算.
NOT 取反.
TEST 测试.(两操作数作与运算,仅修改标志位,不回送结果).
SHL 逻辑左移.
SAL 算术左移.(=SHL)
SHR 逻辑右移.
SAR 算术右移.(=SHR)
ROL 循环左移.
ROR 循环右移.
RCL 通过进位的循环左移.
RCR 通过进位的循环右移.
以上八种移位指令,其移位次数可达255次.
移位一次时, 可直接用操作码. 如 SHL AX,1.
移位>1次时, 则由寄存器CL给出移位次数.
如 MOV CL,04 SHL AX,CL
---------- 四、串指令 ----------------------------------------------------------
DS:SI 源串段寄存器 :源串变址.
ES:DI 目标串段寄存器:目标串变址.
CX 重复次数计数器.
AL/AX 扫描值.
D标志 0表示重复操作中SI和DI应自动增量; 1表示应自动减量.
Z标志 用来控制扫描或比较操作的结束.
MOVS 串传送.( MOVSB 传送字符. MOVSW 传送字. MOVSD 传送双字. )
CMPS 串比较.( CMPSB 比较字符. CMPSW 比较字. )
SCAS 串扫描.把AL或AX的内容与目标串作比较,比较结果反映在标志位.
LODS 装入串.把源串中的元素(字或字节)逐一装入AL或AX中.( LODSB 传送字符. LODSW 传送字. LODSD 传送双字. )
STOS 保存串.是LODS的逆过程.
REP 当CX/ECX<>0时重复.
REPE/REPZ 当ZF=1或比较结果相等,且CX/ECX<>0时重复.
REPNE/REPNZ 当ZF=0或比较结果不相等,且CX/ECX<>0时重复.
REPC 当CF=1且CX/ECX<>0时重复.
REPNC 当CF=0且CX/ECX<>0时重复.
---------- 五、程序转移指令 ----------------------------------------------------
1. 无条件转移指令 (长转移)
JMP 无条件转移指令
CALL 过程调用
RET/RETF 过程返回.
2. 条件转移指令 (短转移,-128到+127的距离内)( 当且仅当(SF XOR OF)=1时,OP1<OP2 )
JA/JNBE 不小于或不等于时转移.
JAE/JNB 大于或等于转移.
JB/JNAE 小于转移.
JBE/JNA 小于或等于转移.
以上四条,测试无符号整数运算的结果(标志C和Z).
JG/JNLE 大于转移.
JGE/JNL 大于或等于转移.
JL/JNGE 小于转移.
JLE/JNG 小于或等于转移.
以上四条,测试带符号整数运算的结果(标志S,O和Z).
JE/JZ 等于转移.
JNE/JNZ 不等于时转移.
JC 有进位时转移.
JNC 无进位时转移.
JNO 不溢出时转移.
JNP/JPO 奇偶性为奇数时转移.
JNS 符号位为 "0" 时转移.
JO 溢出转移.
JP/JPE 奇偶性为偶数时转移.
JS 符号位为 "1" 时转移.
3. 循环控制指令(短转移)
LOOP CX不为零时循环.
LOOPE/LOOPZ CX不为零且标志Z=1时循环.
LOOPNE/LOOPNZ CX不为零且标志Z=0时循环.
JCXZ CX为零时转移.
JECXZ ECX为零时转移.
4. 中断指令
INT 中断指令
INTO 溢出中断
IRET 中断返回
5. 处理器控制指令
HLT 处理器暂停, 直到出现中断或复位信号才继续.
WAIT 当芯片引线TEST为高电平时使CPU进入等待状态.
ESC 转换到外处理器.
LOCK *总线.
NOP 空操作.
STC 置进位标志位.
CLC 清进位标志位.
CMC 进位标志取反.
STD 置方向标志位.
CLD 清方向标志位.
STI 置中断允许位.
CLI 清中断允许位.
---------- 六、伪指令 ----------------------------------------------------------
DW 定义字(2字节).
PROC 定义过程.
ENDP 过程结束.
SEGMENT 定义段.
ASSUME 建立段寄存器寻址.
ENDS 段结束.
END 程序结束.
---------- 七、处理机控制指令:标志处理指令 ------------------------------------
CLC 进位位置0指令
CMC 进位位求反指令
STC 进位位置为1指令
CLD 方向标志置1指令
STD 方向标志位置1指令
CLI 中断标志置0指令
STI 中断标志置1指令
NOP 无操作
HLT 停机
WAIT 等待
ESC 换码
LOCK *
========== 浮点运算指令集 ======================================================
---------- 一、控制指令(带9B的控制指令前缀F变为FN时浮点不检查,机器码去掉9B)----
FINIT 初始化浮点部件 机器码 9B DB E3
FCLEX 清除异常 机器码 9B DB E2
FDISI 浮点检查禁止中断 机器码 9B DB E1
FENI 浮点检查禁止中断二 机器码 9B DB E0
WAIT 同步CPU和FPU 机器码 9B
FWAIT 同步CPU和FPU 机器码 D9 D0
FNOP 无操作 机器码 DA E9
FXCH 交换ST(0)和ST(1) 机器码 D9 C9
FXCH ST(i) 交换ST(0)和ST(i) 机器码 D9 C1iii
FSTSW ax 状态字到ax 机器码 9B DF E0
FSTSW word ptr mem 状态字到mem 机器码 9B DD mm111mmm
FLDCW word ptr mem mem到状态字 机器码 D9 mm101mmm
FSTCW word ptr mem 控制字到mem 机器码 9B D9 mm111mmm
FLDENV word ptr mem mem到全环境 机器码 D9 mm100mmm
FSTENV word ptr mem 全环境到mem 机器码 9B D9 mm110mmm
FRSTOR word ptr mem mem到FPU状态 机器码 DD mm100mmm
FSAVE word ptr mem FPU状态到mem 机器码 9B DD mm110mmm
FFREE ST(i) 标志ST(i)未使用 机器码 DD C0iii
FDECSTP 减少栈指针1->0 2->1 机器码 D9 F6
FINCSTP 增加栈指针0->1 1->2 机器码 D9 F7
FSETPM 浮点设置保护 机器码 DB E4
---------- 二、数据传送指令 ----------------------------------------------------
FLDZ 将0.0装入ST(0) 机器码 D9 EE
FLD1 将1.0装入ST(0) 机器码 D9 E8
FLDPI 将π装入ST(0) 机器码 D9 EB
FLDL2T 将ln10/ln2装入ST(0) 机器码 D9 E9
FLDL2E 将1/ln2装入ST(0) 机器码 D9 EA
FLDLG2 将ln2/ln10装入ST(0) 机器码 D9 EC
FLDLN2 将ln2装入ST(0) 机器码 D9 ED
FLD real4 ptr mem 装入mem的单精度浮点数 机器码 D9 mm000mmm
FLD real8 ptr mem 装入mem的双精度浮点数 机器码 DD mm000mmm
FLD real10 ptr mem 装入mem的十字节浮点数 机器码 DB mm101mmm
FILD word ptr mem 装入mem的二字节整数 机器码 DF mm000mmm
FILD dword ptr mem 装入mem的四字节整数 机器码 DB mm000mmm
FILD qword ptr mem 装入mem的八字节整数 机器码 DF mm101mmm
FBLD tbyte ptr mem 装入mem的十字节BCD数 机器码 DF mm100mmm
FST real4 ptr mem 保存单精度浮点数到mem 机器码 D9 mm010mmm
FST real8 ptr mem 保存双精度浮点数到mem 机器码 DD mm010mmm
FIST word ptr mem 保存二字节整数到mem 机器码 DF mm010mmm
FIST dword ptr mem 保存四字节整数到mem 机器码 DB mm010mmm
FSTP real4 ptr mem 保存单精度浮点数到mem并出栈 机器码 D9 mm011mmm
FSTP real8 ptr mem 保存双精度浮点数到mem并出栈 机器码 DD mm011mmm
FSTP real10 ptr mem 保存十字节浮点数到mem并出栈 机器码 DB mm111mmm
FISTP word ptr mem 保存二字节整数到mem并出栈 机器码 DF mm011mmm
FISTP dword ptr mem 保存四字节整数到mem并出栈 机器码 DB mm011mmm
FISTP qword ptr mem 保存八字节整数到mem并出栈 机器码 DF mm111mmm
FBSTP tbyte ptr mem 保存十字节BCD数到mem并出栈 机器码 DF mm110mmm
FCMOVB ST(0),ST(i) <时传送 机器码 DA C0iii
FCMOVBE ST(0),ST(i) <=时传送 机器码 DA D0iii
FCMOVE ST(0),ST(i) =时传送 机器码 DA C1iii
FCMOVNB ST(0),ST(i) >=时传送 机器码 DB C0iii
FCMOVNBE ST(0),ST(i) >时传送 机器码 DB D0iii
FCMOVNE ST(0),ST(i) !=时传送 机器码 DB C1iii
FCMOVNU ST(0),ST(i) 有序时传送 机器码 DB D1iii
FCMOVU ST(0),ST(i) 无序时传送 机器码 DA D1iii
---------- 三、比较指令 --------------------------------------------------------
FCOM ST(0)-ST(1) 机器码 D8 D1
FCOMI ST(0),ST(i) ST(0)-ST(1) 机器码 DB F0iii
FCOMIP ST(0),ST(i) ST(0)-ST(1)并出栈 机器码 DF F0iii
FCOM real4 ptr mem ST(0)-实数mem 机器码 D8 mm010mmm
FCOM real8 ptr mem ST(0)-实数mem 机器码 DC mm010mmm
FICOM word ptr mem ST(0)-整数mem 机器码 DE mm010mmm
FICOM dword ptr mem ST(0)-整数mem 机器码 DA mm010mmm
FICOMP word ptr mem ST(0)-整数mem并出栈 机器码 DE mm011mmm
FICOMP dword ptr mem ST(0)-整数mem并出栈 机器码 DA mm011mmm
FTST ST(0)-0 机器码 D9 E4
FUCOM ST(i) ST(0)-ST(i) 机器码 DD E0iii
FUCOMP ST(i) ST(0)-ST(i)并出栈 机器码 DD E1iii
FUCOMPP ST(0)-ST(1)并二次出栈 机器码 DA E9
FXAM ST(0)规格类型 机器码 D9 E5
---------- 四、运算指令 --------------------------------------------------------
FADD 把目的操作数 (直接接在指令后的变量或堆栈缓存器) 与来源操作数 (接在目的操作数后的变量或堆栈缓存器) 相加,并将结果存入目的操作数
FADDP ST(i),ST 这个指令是使目的操作数加上 ST 缓存器,并弹出 ST 缓存器,而目的操作数必须是堆栈缓存器的其中之一,最后不管目的操作数为何,经弹出一次后,目的操作数会变成上一个堆栈缓存器了
FIADD FIADD 是把 ST 加上来源操作数,然后再存入 ST 缓存器,来源操作数必须是字组整数或短整数形态的变数
FSUB 减
FSUBP
FSUBR 减数与被减数互换
FSUBRP
FISUB
FISUBR
FMUL 乘
FMULP
FIMUL
FDIV 除
FDIVP
FDIVR
FDIVRP
FIDIV
FIDIVR
FCHS 改变 ST 的正负值
FABS 把 ST 之值取出,取其绝对值后再存回去。
FSQRT 将 ST 之值取出,开根号后再存回去。
FSCALE 这个指令是计算 ST*2^ST(1)之值,再把结果存入 ST 里而 ST(1) 之值不变。ST(1) 必须是在 -32768 到 32768 (-215 到 215 )之间的整数,如果超过这个范围计算结果无法确定,如果不是整数 ST(1) 会先向零舍入成整数再计算。所以为安全起见,最好是由字组整数载入到 ST(1) 里。
FRNDINT 这个指令是把 ST 的数值舍入成整数,FPU 提供四种舍入方式,由 FPU 的控制字组(control word)中的 RC 两个位决定
RC 舍入控制
00 四舍五入
01 向负无限大舍入
10 向正无限大舍入
11 向零舍去
================================================================================
#23
《The Intel 64 and IA-32 Architectures Software Developer's Manual》
#24
再供参考:
#include <stdio.h>
float data[500];
int i;
void main() {
for (i=0;i<500;i++) {data[i]=1.0f;printf("%g\n",data[i]);}
__asm {
push ecx
push edi
mov ecx,500
mov eax,0xBF800000 //-1.0f
lea edi,data
rep stosd
pop edi
pop ecx
}
for (i=0;i<500;i++) printf("%g\n",data[i]);
}
#25
再供参考:#include <stdio.h>
float data[500];
int i;
void main() {
for (i=0;i<500;i++) {data[i]=1.0f;printf("%g\n",data[i]);}
__asm {
push ecx
push edi
mov ecx,500
mov eax,0xBF800000 //-1.0f
lea edi,data
rep stosd
pop edi
pop ecx
}
for (i=0;i<500;i++) printf("%g\n",data[i]);
}
#26
#27
@赵4老师
我先是把程序写成了C语言的形式,就是这一段,用来实现大整数相加的。然后在调试的时候,按“alt+8”,反汇编,然后把反汇编的代码粘贴到相应的位置。结果是,C语言产生的结果正确,而嵌入了汇编的程序,结果完全错误。嗯,应该说是从第三位开始出错。
一下是C语言代码,
然后是反汇编出来的。
,最后是我嵌入的,因为要涉及到跳转,反汇编出来的跳转位置我无法确定,只好把他们分割成不同的小段。
我先是把程序写成了C语言的形式,就是这一段,用来实现大整数相加的。然后在调试的时候,按“alt+8”,反汇编,然后把反汇编的代码粘贴到相应的位置。结果是,C语言产生的结果正确,而嵌入了汇编的程序,结果完全错误。嗯,应该说是从第三位开始出错。
一下是C语言代码,
#include <stdio.h>
#define MAXINT 20
int bigplus(unsigned char a[],unsigned char b[],unsigned char c[]);
int main(int argc, char *argv[])
{
unsigned char a[MAXINT]={10,5,4,6,5,4,3,2,1,1,1}; //被乘数或被除数
unsigned char b[MAXINT]={7,7,6,5,4,3,2,1}; //乘数或除数
unsigned char c[MAXINT],d[MAXINT]; //c[]存放商,d[]存放余数
int div=1234; //小乘数或小除数
int k=0;
int *res=&k; //小余数整数指针
bigplus(a,b,c);
getchar();
return 0;
}
int bigplus(unsigned char a[],unsigned char b[],unsigned char c[]) //大整数加法
{
int i,len;
len=(a[0]>b[0]?a[0]:b[0]); //a[0] b[0]保存数组长度,len为较长的一个
for(i=0;i<MAXINT;i++) //将数组清0
c[i]=0;
for (i=1;i<=len;i++) //计算每一位的值
{
c[i]+=(a[i]+b[i]);
if (c[i]>=10)
{
c[i]-=10; //大于10的取个位
c[i+1]++; //高位加1
}
}
if (c[i+1]>0) len++;
c[0]=len; //c[0]保存结果数组实际长度
printf("Big integers add: ");
for (i=len;i>=1;i--)
printf("%d",c[i]); //打印结果
printf("\n");
return 0;
}
然后是反汇编出来的。
,最后是我嵌入的,因为要涉及到跳转,反汇编出来的跳转位置我无法确定,只好把他们分割成不同的小段。
#28
然后是反汇编出来的。
--- d:\documents\visual studio 2010\projects\调试5\调试5\调试5.cpp -------------------
1: #include <stdio.h>
2: #define MAXINT 20
3:
4: int bigplus(unsigned char a[],unsigned char b[],unsigned char c[]);
5:
6: int main(int argc, char *argv[])
7: {
00DB13A0 push ebp
00DB13A1 mov ebp,esp
00DB13A3 sub esp,158h
00DB13A9 push ebx
00DB13AA push esi
00DB13AB push edi
00DB13AC lea edi,[ebp-158h]
00DB13B2 mov ecx,56h
00DB13B7 mov eax,0CCCCCCCCh
00DB13BC rep stos dword ptr es:[edi]
00DB13BE mov eax,dword ptr [___security_cookie (0DB7000h)]
00DB13C3 xor eax,ebp
00DB13C5 mov dword ptr [ebp-4],eax
8: unsigned char a[MAXINT]={10,5,4,6,5,4,3,2,1,1,1}; //被乘数或被除数
00DB13C8 mov byte ptr [ebp-1Ch],0Ah
00DB13CC mov byte ptr [ebp-1Bh],5
00DB13D0 mov byte ptr [ebp-1Ah],4
00DB13D4 mov byte ptr [ebp-19h],6
00DB13D8 mov byte ptr [ebp-18h],5
00DB13DC mov byte ptr [ebp-17h],4
00DB13E0 mov byte ptr [ebp-16h],3
00DB13E4 mov byte ptr [ebp-15h],2
00DB13E8 mov byte ptr [ebp-14h],1
00DB13EC mov byte ptr [ebp-13h],1
00DB13F0 mov byte ptr [ebp-12h],1
00DB13F4 xor eax,eax
00DB13F6 mov dword ptr [ebp-11h],eax
00DB13F9 mov dword ptr [ebp-0Dh],eax
00DB13FC mov byte ptr [ebp-9],al
9: unsigned char b[MAXINT]={7,7,6,5,4,3,2,1}; //乘数或除数
00DB13FF mov byte ptr [ebp-38h],7
00DB1403 mov byte ptr [ebp-37h],7
00DB1407 mov byte ptr [ebp-36h],6
00DB140B mov byte ptr [ebp-35h],5
00DB140F mov byte ptr [ebp-34h],4
00DB1413 mov byte ptr [ebp-33h],3
00DB1417 mov byte ptr [ebp-32h],2
00DB141B mov byte ptr [ebp-31h],1
00DB141F xor eax,eax
00DB1421 mov dword ptr [ebp-30h],eax
00DB1424 mov dword ptr [ebp-2Ch],eax
00DB1427 mov dword ptr [ebp-28h],eax
10: unsigned char c[MAXINT],d[MAXINT]; //c[]存放商,d[]存放余数
11: int div=1234; //小乘数或小除数
00DB142A mov dword ptr [ebp-7Ch],4D2h
12: int k=0;
00DB1431 mov dword ptr [ebp-88h],0
13: int *res=&k; //小余数整数指针
00DB143B lea eax,[ebp-88h]
00DB1441 mov dword ptr [ebp-94h],eax
14: bigplus(a,b,c);
00DB1447 lea eax,[ebp-54h]
00DB144A push eax
00DB144B lea ecx,[ebp-38h]
00DB144E push ecx
00DB144F lea edx,[ebp-1Ch]
00DB1452 push edx
00DB1453 call bigplus (0DB11B8h)
00DB1458 add esp,0Ch
15:
16: getchar();
00DB145B mov esi,esp
00DB145D call dword ptr [__imp__getchar (0DB82B8h)]
00DB1463 cmp esi,esp
00DB1465 call @ILT+295(__RTC_CheckEsp) (0DB112Ch)
17: return 0;
00DB146A xor eax,eax
18: }
00DB146C push edx
00DB146D mov ecx,ebp
00DB146F push eax
00DB1470 lea edx,[ (0DB149Ch)]
00DB1476 call @ILT+120(@_RTC_CheckStackVars@8) (0DB107Dh)
00DB147B pop eax
00DB147C pop edx
00DB147D pop edi
00DB147E pop esi
00DB147F pop ebx
00DB1480 mov ecx,dword ptr [ebp-4]
00DB1483 xor ecx,ebp
00DB1485 call @ILT+15(@__security_check_cookie@4) (0DB1014h)
00DB148A add esp,158h
00DB1490 cmp ebp,esp
00DB1492 call @ILT+295(__RTC_CheckEsp) (0DB112Ch)
00DB1497 mov esp,ebp
00DB1499 pop ebp
00DB149A ret
00DB149B nop
00DB149C db 05h
00DB149D db 00h
00DB149E db 00h
00DB149F db 00h
00DB14A0 db a4h
00DB14A1 db 14h
00DB14A2 db dbh
00DB14A3 db 00h
00DB14A4 db e4h
00DB14A5 db ffh
00DB14A6 db ffh
00DB14A7 db ffh
00DB14A8 db 14h
00DB14A9 db 00h
00DB14AA db 00h
00DB14AB db 00h
00DB14AC db e8h
00DB14AD db 14h
00DB14AE db dbh
00DB14AF db 00h
00DB14B0 db c8h
00DB14B1 db ffh
00DB14B2 db ffh
00DB14B3 db ffh
00DB14B4 db 14h
00DB14B5 db 00h
00DB14B6 db 00h
00DB14B7 db 00h
00DB14B8 db e6h
00DB14B9 db 14h
00DB14BA db dbh
00DB14BB db 00h
00DB14BC db ach
00DB14BD db ffh
00DB14BE db ffh
00DB14BF db ffh
00DB14C0 db 14h
00DB14C1 db 00h
00DB14C2 db 00h
00DB14C3 db 00h
00DB14C4 db e4h
00DB14C5 db 14h
00DB14C6 db dbh
00DB14C7 db 00h
00DB14C8 db 90h
00DB14C9 db ffh
00DB14CA db ffh
00DB14CB db ffh
00DB14CC db 14h
00DB14CD db 00h
00DB14CE db 00h
00DB14CF db 00h
00DB14D0 db e2h
00DB14D1 db 14h
00DB14D2 db dbh
00DB14D3 db 00h
00DB14D4 db 78h
00DB14D5 db ffh
00DB14D6 db ffh
00DB14D7 db ffh
00DB14D8 db 04h
00DB14D9 db 00h
00DB14DA db 00h
00DB14DB db 00h
00DB14DC db e0h
00DB14DD db 14h
00DB14DE db dbh
00DB14DF db 00h
00DB14E0 db 6bh
00DB14E1 db 00h
00DB14E2 db 64h
00DB14E3 db 00h
00DB14E4 db 63h
00DB14E5 db 00h
00DB14E6 db 62h
00DB14E7 db 00h
00DB14E8 db 61h
00DB14E9 db 00h
--- 无源文件 -----------------------------------------------------------------------
00DB14EA int 3
00DB14EB int 3
00DB14EC int 3
00DB14ED int 3
00DB14EE int 3
00DB14EF int 3
00DB14F0 int 3
00DB14F1 int 3
00DB14F2 int 3
00DB14F3 int 3
00DB14F4 int 3
00DB14F5 int 3
00DB14F6 int 3
00DB14F7 int 3
00DB14F8 int 3
00DB14F9 int 3
00DB14FA int 3
00DB14FB int 3
00DB14FC int 3
00DB14FD int 3
00DB14FE int 3
00DB14FF int 3
00DB1500 int 3
00DB1501 int 3
00DB1502 int 3
00DB1503 int 3
00DB1504 int 3
00DB1505 int 3
00DB1506 int 3
00DB1507 int 3
00DB1508 int 3
00DB1509 int 3
00DB150A int 3
00DB150B int 3
00DB150C int 3
00DB150D int 3
00DB150E int 3
00DB150F int 3
00DB1510 int 3
00DB1511 int 3
00DB1512 int 3
00DB1513 int 3
00DB1514 int 3
00DB1515 int 3
00DB1516 int 3
00DB1517 int 3
00DB1518 int 3
00DB1519 int 3
00DB151A int 3
00DB151B int 3
00DB151C int 3
00DB151D int 3
00DB151E int 3
00DB151F int 3
00DB1520 int 3
00DB1521 int 3
00DB1522 int 3
00DB1523 int 3
00DB1524 int 3
00DB1525 int 3
00DB1526 int 3
00DB1527 int 3
00DB1528 int 3
00DB1529 int 3
00DB152A int 3
00DB152B int 3
00DB152C int 3
00DB152D int 3
00DB152E int 3
00DB152F int 3
00DB1530 int 3
00DB1531 int 3
00DB1532 int 3
00DB1533 int 3
00DB1534 int 3
00DB1535 int 3
00DB1536 int 3
00DB1537 int 3
00DB1538 int 3
00DB1539 int 3
00DB153A int 3
00DB153B int 3
00DB153C int 3
00DB153D int 3
00DB153E int 3
00DB153F int 3
#29
接着
--- d:\documents\visual studio 2010\projects\调试5\调试5\调试5.cpp -------------------
19:
20: int bigplus(unsigned char a[],unsigned char b[],unsigned char c[]) //大整数加法
21: {
00DB1540 push ebp
00DB1541 mov ebp,esp
00DB1543 sub esp,0DCh
00DB1549 push ebx
00DB154A push esi
00DB154B push edi
00DB154C lea edi,[ebp-0DCh]
00DB1552 mov ecx,37h
00DB1557 mov eax,0CCCCCCCCh
00DB155C rep stos dword ptr es:[edi]
22: int i,len;
23: len=(a[0]>b[0]?a[0]:b[0]); //a[0] b[0]保存数组长度,len为较长的一个
00DB155E mov eax,dword ptr [a]
00DB1561 movzx ecx,byte ptr [eax]
00DB1564 mov edx,dword ptr [b]
00DB1567 movzx eax,byte ptr [edx]
00DB156A cmp ecx,eax
00DB156C jle bigplus+3Bh (0DB157Bh)
00DB156E mov ecx,dword ptr [a]
00DB1571 mov dl,byte ptr [ecx]
00DB1573 mov byte ptr [ebp-0D9h],dl
00DB1579 jmp bigplus+46h (0DB1586h)
00DB157B mov eax,dword ptr [b]
00DB157E mov cl,byte ptr [eax]
00DB1580 mov byte ptr [ebp-0D9h],cl
00DB1586 movzx edx,byte ptr [ebp-0D9h]
00DB158D mov dword ptr [len],edx
24: for(i=0;i<MAXINT;i++) //将数组清0
00DB1590 mov dword ptr [i],0
00DB1597 jmp bigplus+62h (0DB15A2h)
00DB1599 mov eax,dword ptr [i]
00DB159C add eax,1
00DB159F mov dword ptr [i],eax
00DB15A2 cmp dword ptr [i],14h
00DB15A6 jge bigplus+73h (0DB15B3h)
25: c[i]=0;
00DB15A8 mov eax,dword ptr [c]
00DB15AB add eax,dword ptr [i]
00DB15AE mov byte ptr [eax],0
00DB15B1 jmp bigplus+59h (0DB1599h)
26: for (i=1;i<=len;i++) //计算每一位的值
00DB15B3 mov dword ptr [i],1
00DB15BA jmp bigplus+85h (0DB15C5h)
00DB15BC mov eax,dword ptr [i]
00DB15BF add eax,1
00DB15C2 mov dword ptr [i],eax
00DB15C5 mov eax,dword ptr [i]
00DB15C8 cmp eax,dword ptr [len]
00DB15CB jg bigplus+0EDh (0DB162Dh)
27: {
28: c[i]+=(a[i]+b[i]);
00DB15CD mov eax,dword ptr [a]
00DB15D0 add eax,dword ptr [i]
00DB15D3 movzx ecx,byte ptr [eax]
00DB15D6 mov edx,dword ptr [b]
00DB15D9 add edx,dword ptr [i]
00DB15DC movzx eax,byte ptr [edx]
00DB15DF add ecx,eax
00DB15E1 mov edx,dword ptr [c]
00DB15E4 add edx,dword ptr [i]
00DB15E7 movzx eax,byte ptr [edx]
00DB15EA add eax,ecx
00DB15EC mov ecx,dword ptr [c]
00DB15EF add ecx,dword ptr [i]
00DB15F2 mov byte ptr [ecx],al
29: if (c[i]>=10)
00DB15F4 mov eax,dword ptr [c]
00DB15F7 add eax,dword ptr [i]
00DB15FA movzx ecx,byte ptr [eax]
00DB15FD cmp ecx,0Ah
00DB1600 jl bigplus+0EBh (0DB162Bh)
30: {
31: c[i]-=10; //大于10的取个位
00DB1602 mov eax,dword ptr [c]
00DB1605 add eax,dword ptr [i]
00DB1608 movzx ecx,byte ptr [eax]
00DB160B sub ecx,0Ah
00DB160E mov edx,dword ptr [c]
00DB1611 add edx,dword ptr [i]
00DB1614 mov byte ptr [edx],cl
32: c[i+1]++; //高位加1
00DB1616 mov eax,dword ptr [c]
00DB1619 add eax,dword ptr [i]
00DB161C mov cl,byte ptr [eax+1]
00DB161F add cl,1
00DB1622 mov edx,dword ptr [c]
00DB1625 add edx,dword ptr [i]
00DB1628 mov byte ptr [edx+1],cl
33: }
34: }
00DB162B jmp bigplus+7Ch (0DB15BCh)
35: if (c[i+1]>0) len++;
00DB162D mov eax,dword ptr [c]
00DB1630 add eax,dword ptr [i]
00DB1633 movzx ecx,byte ptr [eax+1]
00DB1637 test ecx,ecx
00DB1639 jle bigplus+104h (0DB1644h)
00DB163B mov eax,dword ptr [len]
00DB163E add eax,1
00DB1641 mov dword ptr [len],eax
36: c[0]=len; //c[0]保存结果数组实际长度
00DB1644 mov eax,dword ptr [c]
00DB1647 mov cl,byte ptr [len]
00DB164A mov byte ptr [eax],cl
37: printf("Big integers add: ");
00DB164C mov esi,esp
00DB164E push offset string "Big integers add: " (0DB5744h)
00DB1653 call dword ptr [__imp__printf (0DB82B4h)]
00DB1659 add esp,4
00DB165C cmp esi,esp
00DB165E call @ILT+295(__RTC_CheckEsp) (0DB112Ch)
38: for (i=len;i>=1;i--)
00DB1663 mov eax,dword ptr [len]
00DB1666 mov dword ptr [i],eax
00DB1669 jmp bigplus+134h (0DB1674h)
00DB166B mov eax,dword ptr [i]
00DB166E sub eax,1
00DB1671 mov dword ptr [i],eax
00DB1674 cmp dword ptr [i],1
00DB1678 jl bigplus+15Dh (0DB169Dh)
39: printf("%d",c[i]); //打印结果
00DB167A mov eax,dword ptr [c]
00DB167D add eax,dword ptr [i]
00DB1680 movzx ecx,byte ptr [eax]
00DB1683 mov esi,esp
00DB1685 push ecx
00DB1686 push offset string "%d" (0DB5740h)
00DB168B call dword ptr [__imp__printf (0DB82B4h)]
00DB1691 add esp,8
00DB1694 cmp esi,esp
00DB1696 call @ILT+295(__RTC_CheckEsp) (0DB112Ch)
00DB169B jmp bigplus+12Bh (0DB166Bh)
40: printf("\n");
00DB169D mov esi,esp
00DB169F push offset string "\n" (0DB573Ch)
00DB16A4 call dword ptr [__imp__printf (0DB82B4h)]
00DB16AA add esp,4
00DB16AD cmp esi,esp
00DB16AF call @ILT+295(__RTC_CheckEsp) (0DB112Ch)
41: return 0;
00DB16B4 xor eax,eax
42: }
00DB16B6 pop edi
00DB16B7 pop esi
00DB16B8 pop ebx
00DB16B9 add esp,0DCh
00DB16BF cmp ebp,esp
00DB16C1 call @ILT+295(__RTC_CheckEsp) (0DB112Ch)
00DB16C6 mov esp,ebp
00DB16C8 pop ebp
00DB16C9 ret
#30
代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。
提醒:再牛×的老师也无法代替学生自己领悟和上厕所!
单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
提醒:再牛×的老师也无法代替学生自己领悟和上厕所!
单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
#31
最后是我嵌入C语言的代码。
因为原始的的反汇编代码,要跳转,而且跳转的位置还是直接用地址表示的。而我在编写的时候无法知道地址信息。所以一开始我是把相应的地址对应的行给标上一个名字,比如jmp jisuan。然后我把某一行前面标上jisuan:,然而,运行的结果是,貌似电脑无法识别这种标识。当然了,我记得在编写纯粹的汇编语言代码时是可以的,但是也许在C语言中是无法识别的。当然,没有报错,只是结果不对。
然后我把对应的跳转程序,分成一个个的小段,从这段跳转到另一段。结果是,程序不报错,但是结果不对。只有个位和十位正确,从百位开始就错了。往后更是都变成了0。
如果您忙的话,不用仔细看程序,跟我说说我是不是引用的格式(或者方式)不对啊。
#include<stdio.h>
# define MAXINT 20
int bigplus(unsigned char a[],unsigned char b[],unsigned char c[]);
int main(int argc, char *argv[])
{
unsigned char a[MAXINT]={10,0,9,8,7,6,5,4,3,2,1};
unsigned char b[MAXINT]={8,8,7,6,5,4,3,2,1};
unsigned char c[MAXINT],d[MAXINT]; //c[]存放商,d[]存放余数,g[]是除法时每次相乘的结果
bigplus(a,b,c);
return 0;
}
int bigplus(unsigned char a[],unsigned char b[],unsigned char c[])
{
int i,len;
len=(a[0]>b[0]?a[0]:b[0]); //a[0] b[0]保存数组长度,len为较长的一个
printf("len=%d\n",len);
for(i=0;i<MAXINT;i++) //将数组清0
{
c[i]=0;
}
__asm
{
mov dword ptr [i],1
jmp dian
}
dian:
__asm
{
mov eax,dword ptr [i]
cmp eax,dword ptr [len]
jg dian2
//c[i]+=(a[i]+b[i]);
mov eax,dword ptr [a]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax]
mov edx,dword ptr [b]
add edx,dword ptr [i]
movzx eax,byte ptr [edx]
add ecx,eax
mov edx,dword ptr [c]
add edx,dword ptr [i]
movzx eax,byte ptr [edx]
add eax,ecx
mov ecx,dword ptr [c]
add ecx,dword ptr [i]
mov byte ptr [ecx],al
// if (c[i]>=10)
mov eax,dword ptr [c]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax]
cmp ecx,0Ah
jl dian3 //小于10,跳转到开始循环位置
// c[i]-=10; //大于10的取个位
mov eax,dword ptr [c]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax]
sub ecx,0Ah
mov edx,dword ptr [c]
add edx,dword ptr [i]
mov byte ptr [edx],cl
// c[i+1]++; //高位加1
mov eax,dword ptr [c]
add eax,dword ptr [i]
mov cl,byte ptr [eax+1]
add cl,1
mov edx,dword ptr [c]
add edx,dword ptr [i]
mov byte ptr [edx+1],cl
// jmp bigplus+7Ch (13315BCh)
}
dian3:
__asm
{
mov eax,dword ptr [i]
add eax,1
mov dword ptr [i],eax
mov eax,dword ptr [i]
cmp eax,dword ptr [len]
jg dian2
//c[i]+=(a[i]+b[i]);
mov eax,dword ptr [a]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax]
mov edx,dword ptr [b]
add edx,dword ptr [i]
movzx eax,byte ptr [edx]
add ecx,eax
mov edx,dword ptr [c]
add edx,dword ptr [i]
movzx eax,byte ptr [edx]
add eax,ecx
mov ecx,dword ptr [c]
add ecx,dword ptr [i]
mov byte ptr [ecx],al
// if (c[i]>=10)
mov eax,dword ptr [c]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax]
cmp ecx,0Ah
jl dian3
// jl bg //小于10,跳转到开始循环位置
// c[i]-=10; //大于10的取个位
mov eax,dword ptr [c]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax]
sub ecx,0Ah
mov edx,dword ptr [c]
add edx,dword ptr [i]
mov byte ptr [edx],cl
// c[i+1]++; //高位加1
mov eax,dword ptr [c]
add eax,dword ptr [i]
mov cl,byte ptr [eax+1]
add cl,1
mov edx,dword ptr [c]
add edx,dword ptr [i]
mov byte ptr [edx+1],cl
// jmp bigplus+7Ch (13315BCh)
}
dian2:
__asm
{
mov eax,dword ptr [c]
add eax,dword ptr [i]
movzx ecx,byte ptr [eax+1]
test ecx,ecx
jle dian4
mov eax,dword ptr [len]
add eax,1
mov dword ptr [len],eax
jmp dian4
}
// c[0]=len; //c[0]保存结果数组实际长度
dian4:
__asm
{
mov eax,dword ptr [c]
mov cl,byte ptr [len]
mov byte ptr [eax],cl
}
printf("Big integers add: ");
// printf("10进制:");
for (i=len;i>=1;i--)
{
printf("%d,",c[i]); //打印结果
}
printf("\n");
return 0;
}
因为原始的的反汇编代码,要跳转,而且跳转的位置还是直接用地址表示的。而我在编写的时候无法知道地址信息。所以一开始我是把相应的地址对应的行给标上一个名字,比如jmp jisuan。然后我把某一行前面标上jisuan:,然而,运行的结果是,貌似电脑无法识别这种标识。当然了,我记得在编写纯粹的汇编语言代码时是可以的,但是也许在C语言中是无法识别的。当然,没有报错,只是结果不对。
然后我把对应的跳转程序,分成一个个的小段,从这段跳转到另一段。结果是,程序不报错,但是结果不对。只有个位和十位正确,从百位开始就错了。往后更是都变成了0。
如果您忙的话,不用仔细看程序,跟我说说我是不是引用的格式(或者方式)不对啊。
#32
试试:
项目、属性、配置属性、C/C++、输出文件、汇编程序输出:程序集、机器码和源代码(/Facs)
在重新编译,查看生成的.asm文件内容。
项目、属性、配置属性、C/C++、输出文件、汇编程序输出:程序集、机器码和源代码(/Facs)
在重新编译,查看生成的.asm文件内容。
#33
再重新编译
#34
代码功能归根结底不是别人帮自己看或讲解或注释出来的;而是被自己静下心来花足够长的时间和精力亲自动手单步或设断点或对执行到某步获得的中间结果显示或写到日志文件中一步一步分析出来的。
提醒:再牛×的老师也无法代替学生自己领悟和上厕所!
单步调试和设断点调试(VS IDE中编译连接通过以后,按F10或F11键单步执行,按Shift+F11退出当前函数;在某行按F9设断点后按F5执行停在该断点处。)是程序员必须掌握的技能之一。
#35
VC调试时按Alt+8、Alt+7、Alt+6和Alt+5,打开汇编窗口、堆栈窗口、内存窗口和寄存器窗口看每句C对应的汇编、单步执行并观察相应堆栈、内存和寄存器变化,这样过一遍不就啥都明白了吗。
#36
哈哈哈哈,嵌入成功了。感谢赵老师@赵4老师 ,感谢楼上各位的帮助。谢谢大家!!!!
#37
哈哈哈哈,嵌入成功了。感谢赵老师@赵4老师 ,感谢楼上各位的帮助。谢谢大家!!!!
小确幸!
#38
哈哈哈哈,嵌入成功了。感谢赵老师@赵4老师 ,感谢楼上各位的帮助。谢谢大家!!!!
一开始接手这个任务时,我信心满满,可是当自己着手开始做的时候,才发现,对于一个512位的数据,我怎么表示,这就成了第一大难关,如果不解决了,接下来的计算就无法进行。之后我试着位运算来计算加减乘除,可是,却不知道减法和乘法如何实现,更别提除法了。于是只好用C语言的算术运算来解决。被老师狠狠地批了一顿,并要求我必须用汇编或者位运算来完成计算过程。从此接近5天了,终于把汇编嵌入到了C语言中。虽然对开学之前完成整个工作抱有悲观看法,但是还是要继续努力做下去。总之要把它完成。
#39
老师也有老师对的地方和难处。
#40
老师也有老师对的地方和难处。
#41
恭喜,蹭点分
#42
恭喜,蹭点分
欢迎欢迎
#43
你只是源码级别的嵌入,我们可以考虑目标文件级别的嵌入。即汇编代码用汇编程序编译成目标文件,C语言代码用C编译器编译成目标文件,然后利用连接器链接这两个目标文件。