masm能通过,tasm不能通过
是用c调用汇编的汇编部分
tasm能通过,masm不能通过
因为汇编不是很好,近来看得很头疼
谁帮调试一下,让它能在masm通过编译
C调用汇编扩展读
下面是代码
;********************************************
;文件名:EAR.ASM
;功能:读硬盘扇区数据并建立存储文件
;********************************************
count=512 ;1.定义常量
disk struc ;2.定义结构
packetsize db 16 ;3.
reserved db 0 ;4.
blockcount dw 1 ;5.
bufferaddr dd 200h ;6.
blocknum dq ? ;7.
disk ends ;8.
;9.
.model small ;10.定义编译模式
.data ;11.定义数据段
buff disk <> ;12.
.code ;13.定义代码段
public _rhd ;14.声明为公有标识符
_rhd proc ;15.子程序开始
push bp ;16.保护现场
mov bp,sp ;17.保存堆栈指针
push ds ;18.保护现场
push si ;19.保护现场
push di ;20.保护现场
;21.
mov ah,42h ;22.磁盘读
mov dl,80h ;23.第一硬盘
mov di,offset buff.blocknum ;24.取结构变量成员地址
mov bx,[bp+10] ;25.取第一个字节参数
mov [di],bx ;26.存入变量成员第一个字
mov bx,[bp+8] ;27.取第二个字节参数
mov [di+1],bx ;28.存入变量成员第二个字
mov bx,[bp+6] ;29.取第三个字节参数
mov [di+2],bx ;30.存入变量成员第三个字
mov bx,[bp+4] ;31.取第四个字节参数
mov [di+3],bx ;32.存入变量成员第四个字
mov si,offset buff ;33.取数据包地址
int 13h ;34.调用中断
;35.
mov dx,[bp+12] ;36.取文件名
mov cx,0 ;37.
mov ah,3ch ;38.建立文件
int 21h ;39.
mov bx,ax ;40.保存文件号
lds dx,buff.bufferaddr ;41.取数据缓冲区地址
mov cx,count ;42.取字节数
mov ah,40h ;43.写文件
int 21h ;44.
mov ah,3eh ;45.关闭文件
int 21h ;46.
pop di ;47.恢复现场
pop si ;48.恢复现场
pop ds ;49.恢复现场
pop bp ;50.恢复现场
ret ;51.子程序返回
_rhd endp ;52.子程序结束
end ;53.程序结束
报错如下
41行:error A2074: cannot access label through segment registers
[解决办法]
在 masm611 下编译连接没有错误:
C:\MASM611\BIN> ml m.asm
Microsoft (R) Macro Assembler Version 6.11
Copyright (C) Microsoft Corp 1981-1993. All rights reserved.
Assembling: m.asm
Microsoft (R) Segmented Executable Linker Version 5.31.009 Jul 13 1992
Copyright (C) Microsoft Corp 1984-1992. All rights reserved.
Object Modules [.obj]: m.obj
Run File [m.exe]: "m.exe "
List File [nul.map]: NUL
Libraries [.lib]:
Definitions File [nul.def]:
LINK : warning L4021: no stack segment
LINK : warning L4038: program has no starting address
C:\MASM611\BIN>
[解决办法]
你肯定安装拉MASM32, 你得用16位的linker 重新下一个masm
[解决办法]
汇编完全可以通过,只不过在保护方式下运行此程序计算机会错。下面看一看生成的列表文件:
Microsoft (R) Macro Assembler Version 6.15.8803 02/11/07 14:25:53
ear.asm Page 1 - 1
= 0200count=512 ;1.定义常量
0010disk struc ;2.定义结构
0000 10packetsize db 16 ;3.
0001 00reserved db 0 ;4.
0002 0001blockcount dw 1 ;5.
0004 00000200bufferaddr dd 200h ;6.
0008 0000000000000000blocknum dq ? ;7.
disk ends ;8.
;9.
.model small ;10.定义编译模式
0000.data ;11.定义数据段
0000 10 00 0001 00000200buff disk <> ;12.
0000000000000000
0000.code ;13.定义代码段
public _rhd ;14.声明为公有标识符
0000_rhd proc ;15.子程序开始
0000 55 push bp ;16.保护现场
0001 8B EC mov bp,sp ;17.保存堆栈指针
0003 1E push ds ;18.保护现场
0004 56 push si ;19.保护现场
0005 57 push di ;20.保护现场
;21.
0006 B4 42 mov ah,42h ;22.磁盘读
0008 B2 80 mov dl,80h ;23.第一硬盘
000A BF 0008 R mov di,offset buff.blocknum ;24.取结构变量成员地址
000D 8B 5E 0A mov bx,[bp+10] ;25.取第一个字节参数
0010 89 1D mov [di],bx ;26.存入变量成员第一个字
0012 8B 5E 08 mov bx,[bp+8] ;27.取第二个字节参数
0015 89 5D 01 mov [di+1],bx ;28.存入变量成员第二个字
0018 8B 5E 06 mov bx,[bp+6] ;29.取第三个字节参数
001B 89 5D 02 mov [di+2],bx ;30.存入变量成员第三个字
001E 8B 5E 04 mov bx,[bp+4] ;31.取第四个字节参数
0021 89 5D 03 mov [di+3],bx ;32.存入变量成员第四个字
0024 BE 0000 R mov si,offset buff ;33.取数据包地址
0027 CD 13 int 13h ;34.调用中断
;35.
0029 8B 56 0C mov dx,[bp+12] ;36.取文件名
002C B9 0000 mov cx,0 ;37.
002F B4 3C mov ah,3ch ;38.建立文件
0031 CD 21 int 21h ;39.
0033 8B D8 mov bx,ax ;40.保存文件号
0035 C5 16 0004 R lds dx,buff.bufferaddr ;41.取数据缓冲区地址
0039 B9 0200 mov cx,count ;42.取字节数
003C B4 40 mov ah,40h ;43.写文件
003E CD 21 int 21h ;44.
0040 B4 3E mov ah,3eh ;45.关闭文件
0042 CD 21 int 21h ;46.
0044 5F pop di ;47.恢复现场
0045 5E pop si ;48.恢复现场
0046 1F pop ds ;49.恢复现场
0047 5D pop bp ;50.恢复现场
0048 C3 ret ;51.子程序返回
0049_rhd endp ;52.子程序结束
end ;53.程序结
Microsoft (R) Macro Assembler Version 6.15.8803 02/11/07 14:25:53
ear.asm Symbols 2 - 1
[解决办法]
谁知道三国时期的木牛流马是什么原理?为什么不吃草料,而且可以不用人力而自由行走?难道诸葛亮是神仙吗?他会法术?不懂得它的机制,就开始操作它,甚至是在它不能正确运转或运行的时候试图解决它,瞎猫有多大的几率可以碰到死耗子?即便是糊里糊涂的编译通过,我们的心里舒服吗?不懂得实体的基本机制,就不能顺利的使用它,更不能灵活的使用它。所以,我们要研究编译器,这样的要求好像有些苛刻,但是,这可以在很多程度上减少我们在编译、调试程序上所花费的时间,而且可以从编译器的角度优化我们的代码。嫌话话说多了,切入正题,解决问题:
根据下面的常量(标号)定义:
count=512
编译器编译源程序出错,它告诉我们,错误在41行,不能通过段寄存器访问标号。
41行:error A2074: cannot access label through segment registers
我们找到41行,代码如下:
mov cx,count ;42.取字节数
代码给cx赋了一个标号count,在C、C++语言,给变量赋常量(标号)是可以的。在汇编语言里,有些编译器支持给寄存器赋标号,这样的编译器在编译时执行预处理,采用宏替换的方式把标号代表的值取出,以立即数的形式嵌入到源代码中,预处理后,源代码变成了:“mov cx,512”,然后继续编译,正称楼主的意思。而有些编译器把标号看作段内偏移地址,这样的编译器编译,可能通过,也可能通不过编译检查,即便通过和,在程序执行时,也可能造成逻辑上的错误,导致程序读取到错误的数据,难以纠错。有些编译器,一般为高级语言编译器内含的汇编器,这样的编译器,功能比较简单,没有宏替换的功能,这样的编译器发现给寄存器赋标号时,给出错误信息,这样的编译器支持立即数赋值和地址赋值,虽然不灵活,但却可以避免运行时的错误发生,避免了可能发生的逻辑错误。
修改源代码:
将mov cx,count改为mov cx,200H, 或者只在在数据段加入:count dw 200H ,但要删除调下面的常量定义:“count=512 ;1.定义常量”