首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 嵌入开发 > 汇编语言 >

masm能通过,tasm不能通过解决思路

2012-03-21 
masm能通过,tasm不能通过是用c调用汇编的汇编部分tasm能通过,masm不能通过因为汇编不是很好,近来看得很头

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.定义常量”


热点排行