初学 汇编和asm的问题

okmnji79513 2008-12-23 01:27:11
我在王爽书上看到一个例子:

mov ax,2000h
mov ds,ax
mov bx,1000h
mov ax,[bx]
inc bx
inc bx
mov [bx],ax
......

这是一个就内存中21000h~~21007h单元内容的例子,其中21000h内容为'BE',21007h内容为'00'(第5章 问题5.1)
这个例子我能理解。

然后我在delphi中
function TForm1.A10(i:integer):integer;
begin
asm
mov ecx,1000h
mov eax,1500h
mov [eax],ecx --------------- (1)
mov result,eax
end;
end;

function TForm1.A11(i:integer):integer;
begin
asm
mov ecx,1000h
mov eax,1500h
mov [ecx],1h --------------- (2)
mov eax,[ecx] --------------- (3)
mov result,eax
end;
end;

在调用它们时,(1)(2)(3)处有[]处,都会报内存错误。
我想问下在delphi中,函数里用eax等寄存器,都只是当变量使用(其中的含义异于一般汇编语句)?还是因为该地址内存不可改?还是什么别的原因?
在delphi的函数中能不能用[],怎么用?

菜鸟问题,请多帮助,谢谢。
...全文
153 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
okmnji79513 2008-12-24
  • 打赏
  • 举报
回复
感谢 指导
先学习下D7的帮助
  • 打赏
  • 举报
回复
前面说的只是针对register/fastcall调用约定,对一些“标准”的调用约定,象cdecl、pascal、stdcall等,不同的编译器之间还是遵循相同的标准的。
yc_8301 2008-12-23
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 DelphiGuy 的回复:]
引用 10 楼 okmnji79513 的回复:
'对于Delphi默认的register调用约定,eax、edx、ecx包含3个参数(如果有的话)' 对于这个我想问下:如C++中是否就不同了呢?还是对所有的语言都是'默认的register调用约定,eax、edx、ecx包含3个参数(如果有的话)'?
如果不是的话,那这些资料(如'eax、edx、ecx包含前3个参数(如果有的话)',eax默认作为返回值)从哪里可以学习到?(看delphi源码?+经验积累?)因为一般的 汇编 教程的话…
[/Quote]
哦。学习了。。期待更多相关的内容.......
huangjacky 2008-12-23
  • 打赏
  • 举报
回复
王爽这书我也在看.
书里面不停的说用cmd-debug写汇编程序,郁闷死人了.
汇编程序或者语句用什么写?
大家推荐下.
  • 打赏
  • 举报
回复
[Quote=引用 10 楼 okmnji79513 的回复:]
'对于Delphi默认的register调用约定,eax、edx、ecx包含3个参数(如果有的话)' 对于这个我想问下:如C++中是否就不同了呢?还是对所有的语言都是'默认的register调用约定,eax、edx、ecx包含3个参数(如果有的话)'?
如果不是的话,那这些资料(如'eax、edx、ecx包含前3个参数(如果有的话)',eax默认作为返回值)从哪里可以学习到?(看delphi源码?+经验积累?)因为一般的 汇编 教程的话不会讲这些吧。
[/Quote]

这是与编译器相关的,不同的编译器处理参数的方法不能保证一样。
Delphi和C++ Builder的参数处理方法是一样的,Delphi的register调用约定在C++ Builder中叫__fastcall,
但是ms的编译器就和Delphi/C++ Builder处理参数的方法不同,VC++的__fastcall是用ecx、edx传送前2个参数(注意是左面开始的两个),这种调用约定在C++ Builder中叫__msfastcall。
这些在帮助文档中都有的。
liangpei2008 2008-12-23
  • 打赏
  • 举报
回复
学习,顺便顶一下楼上的问题
okmnji79513 2008-12-23
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 DelphiGuy 的回复:]
没有任何版本的Delphi“edx默认接收第一个参数值”,对于Delphi默认的register调用约定,eax、edx、ecx包含3个参数(如果有的话),但是有一个例外:浮点参数永远不使用寄存器传递。
[/Quote]

'对于Delphi默认的register调用约定,eax、edx、ecx包含3个参数(如果有的话)' 对于这个我想问下:如C++中是否就不同了呢?还是对所有的语言都是'默认的register调用约定,eax、edx、ecx包含3个参数(如果有的话)'?
如果不是的话,那这些资料(如'eax、edx、ecx包含前3个参数(如果有的话)',eax默认作为返回值)从哪里可以学习到?(看delphi源码?+经验积累?)因为一般的 汇编 教程的话不会讲这些吧。
  • 打赏
  • 举报
回复
eax、edx、ecx包含前3个参数(如果有的话)
  • 打赏
  • 举报
回复
返回值就在eax(或者edx:eax=int64)中,所以这句mov result,eax 一点用没有,你反汇编看就是mov eax,eax。
至于你举的例子,后面的showmessage('aa');又使用了eax,你之后又没有再设置返回值,当然就不对了。

没有任何版本的Delphi“edx默认接收第一个参数值”,对于Delphi默认的register调用约定,eax、edx、ecx包含3个参数(如果有的话),但是有一个例外:浮点参数永远不使用寄存器传递。


okmnji79513 2008-12-23
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 DelphiGuy 的回复:]
mov result,eax // 这句其实没用,去掉也可以
[/Quote]

我看这句还是留着吧,我这样

function TForm1.A10(i:integer):integer;
begin
asm
mov eax,edx //或用mov eax,i
end;
showmessage('aa');
end;

它的返回值就不对了。

还有edx是不是默认接收第一个参数值?我怎么感觉有时是有时不是?不同的版本也会不同吧?
okmnji79513 2008-12-23
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 zwjchina 的回复:]
DelphiGuy不厚道。只帮小孩子抓鱼,不教小孩子抓鱼。
[/Quote]

愿闻其详
zwjchina 2008-12-23
  • 打赏
  • 举报
回复
DelphiGuy不厚道。只帮小孩子抓鱼,不教小孩子抓鱼。
  • 打赏
  • 举报
回复
这样改一下:
function TForm1.A11(i:integer):integer;
var
a, b: integer;
begin
asm
lea ecx,a
lea eax,b
mov [a],1h
mov eax,[a]
mov result,eax // 这句其实没用,去掉也可以
end;
end;
  • 打赏
  • 举报
回复
[]表示地址,当然可以用。
出错是因为你给出的地址有问题,在win32的程序模型中,虽然有4GB地址空间,但是不是都可使用的,2GB~3GB是用于程序引用的DLLs,3GB以上用于系统内核,低2GB的高低两端各64KB用于捕获NULL指针操作(你程序中用到的地址恰好就位于低64KB之内),也不可访问。即便剩余的不足2GB空间,也要先分配再使用,否则就是“虚”的,只有地址,没有物理内存与之对应。
panrongzeng 2008-12-23
  • 打赏
  • 举报
回复
你看看Windows单元,里面有很多例子。其他单元也有
僵哥 2008-12-23
  • 打赏
  • 举报
回复
不能随便往一个“绝对”地址写入内容。内存是需要先分配后使用的。
【例2.8】存储器与寄存器间数据传送。 MOV AX,BUF ;BUF是变量,源操作数为直接寻址 MOV BH,[DI] ;源操作数为寄存器间接寻址 MOV DI,ES:3[SI] ;源操作数为变址寻址,使用跨段前缀 MOV BP,3[BX+SI] ;源操作数为基址加变址寻址 MOV BUFA,DL ;BUFA是一字节变量 MOV [BP],AX ;使用SS段寄存器 MOV DS:[BP],DL ;使用跨段前缀 MOV BUF,DS ;BUF是个字变量 MOV ES ,BUF 【例2.10】将一种代码转换成另一种代码。 【例2.16】更改数据段段首址。 【例2.23】带借位减运算。 【例2.48】比较数据中STR1字符串和附加段中STR2字符串是否相同。 假设两个字符串长度一样,为COUNT个字节。比较的结果存入RESULT单元, 结果为0表示相等,为-1(即FFH)表示不等。 【例2.51】用重复前缀比较两个字符串相等。 【例2.55】把数据区的数据按正、负数分开,并分别送至两个缓冲区。 【例2.56】利用子程序完成将AL低4位中的一位16进制数转换成对应的ASCII码 【例3.4】用算术运算符进行数值表达式运算。 【例3.7】用属性运算符表示类型属性。 【例3.8】下面程序段的某些语句是错误的。 【例3.9】用属性运算符定义新变量 【例3.11】分离变量类型。 【例6.5】用软中断INT 60H、发声中断服务程序INT 61H以及软中断INT 62H、 INT 63H , 实现字符串“intel 80486 DX2/66 CPU”显示、扬声器发声和变色三角形的显示功能, 定时器ICH中断作为计数器使用。 ................................................................ ................................................................ 7.1 实验步骤 在PC机上运行汇编程序必须经过以下几个步骤: (1)编辑源程序。利用文本编辑工具编辑源程序, 生成一个汇编语言源程序的纯文本文件?惚嘤镅栽闯绦虻睦┱姑?签qASM。 (2)汇编源程序。用汇编汇编源程序生成目标代码文件,目标代码文件的扩展名 是?OBJ,汇编器还可以生成列表文件和交叉参考文件?如果源程序有语法错误行, 汇编器就不生成目标代码文件。这时,必须重新编辑源程序,修改语法错误的行。 当发现源程序中的某些行含不确定因素时,汇编器会给出警告信息,但仍按缺省处 理办法生成目标代码文件。此时,可以重新编辑源程序,消除不确定因素。 (3)连接目标程序。利用连接器连接目标代码程序和库函数代码生成可执行程序文件。 通常DOS平台上的可执行程序文件的扩展名是?EXE。一般单个? 或者与库函数连接时,如果在目标代码文件或者库中找不到所需的连接信息, 连接器就会发生错误提示信息,而不生成可执行程序文件。这时,就要重新编辑源程序, 并汇编源程序。 (4)调试可执行程序。程序的动态调试是在形成可执行程序文件后,针对可执行程序进行的。 DEBUG是简单而有效的动态调试工具,利用调试工具动态地调试程序,找出程序中的问题。 如果发现程序中有问题,那么必须重新编辑、汇编源程序。 下面以一个简单的例子说明汇编源程序的上机过程。 假定要在显示器显示如下一行信息: I am a student! 那么,其汇编源程序的过程如下: STACK SEGMENT STACK DB 200 DUP(0) STACK ENDS DATA SEGM0ENT BUF DB I am a student!$ DATA ENDS CODE SEBMENT ASSUME CS:CODE,DS:DATA,SS:STACK START: MOV AX,DATA MOV DS,AX LEA DX,BUF MOV AH,9 INT 21H MOV AH,4CH INT 21H CODE ENDS END START 第一步:编辑源程序。假定源文件名为EXAM?ASM。 第二步:汇编源程序EXAM?ASM。 A>MASM EXAM ; 此命令是调用宏汇编程序MASM对源文件EXAM?ASM进行汇编,生成目标文件EXAM?OBJ. 若汇编无错误,则进入第三步。 第三步:连接目标程序文件EXAM?OBJ。 A>LINK EXAM ; 若连接成功,则进入下一步。 第四步:运行可执行文件EXAM?EXE A>EXAM 运行结果如下: I am a student! 若未得到预期的结果,可检查EXAM?ASM文件内容,修改错误,再次汇编、连接、运行,直到满意为止。

1,183

社区成员

发帖
与我相关
我的任务
社区描述
Delphi Windows SDK/API
社区管理员
  • Windows SDK/API社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧