能力值:
( LV2,RANK:10 )
2 楼
古董级的东西还有人在用!
能力值:
( LV3,RANK:20 )
3 楼
是的,我的一个朋友要求必须做的,我都快哭了,asm和传感器的通讯我一点都不懂
能力值:
( LV2,RANK:10 )
4 楼
分析一下通信协议,应该是串口吧?RS232
能力值:
( LV3,RANK:20 )
5 楼
这个设备都不在我身边,我连见都没见过
能力值:
(RANK: )
6 楼
用0x2E8(通常是Com4)与某设备进行通讯, 应该只是端口I/O部分, 具体的数据分析还是在VFP程序里的.
如果没有设备, 还不如直接反编译VFP程序, 找出它的调用参数和数据处理算法, 看看能否跳过或替代.
能力值:
( LV3,RANK:20 )
7 楼
PUBLIC s_fr, s_f1r, s_br, s_b1r, s_xr, s_x1r, s_pr, s_p1r, s_gr, ;
s_g1r, s_sr, s_s1r, s_fl, s_f1l, s_bl, s_b1l, s_xl, s_x1l, ;
s_pl, s_p1l, s_gl, s_g1l, s_sl, s_s1l, xzz, row1, coiumn1, ;
size_h1, size_v1, pict1, row2, coiumn2, size_h2, size_v2, ;
pict2
xzz = 1
s_fr = ""
s_f1r = ""
s_br = ""
s_b1r = ""
s_xr = ""
s_x1r = ""
s_pr = ""
s_p1r = ""
s_gr = ""
s_g1r = ""
s_sr = ""
s_s1r = ""
s_fl = ""
s_f1l = ""
s_bl = ""
s_b1l = ""
s_xl = ""
s_x1l = ""
s_pl = ""
s_p1l = ""
s_gl = ""
s_g1l = ""
s_sl = ""
s_s1l = ""
PUBLIC gcom, gcomuse, gcomt, gcomn
gcom = 1
gcomuse = 0
gcomt = 0.1
gcomn = 1
IF FILE("GCOM.MEM")
RESTORE FROM GCOM ADDITIVE
ENDIF
load z0
load zy
IF gcomuse = 1
WAIT WINDOW NOWAIT "请连接测试仪..."
CALL zo WITH CHR(gcom - 1)
WAIT CLEAR
ENDIF
此后就对上面初始化的这些变量开始正式调用,也就是说,这个zo.bin 被load后再call一下就完成了上面一组内存变量的赋值。
能力值:
(RANK: )
8 楼
仔细看了一下, ZO里所做的事只是测试那个"测试仪"是否存在(接口参数为1200, 8-N-1), 入口参数为对应所连接的Com口.
具体的流程是
1. 按1200, 8-N-1设置Com口
2. 发送10个字节 "EE 30 36 30 39 32 37 39 31 EE"
3. 等待并检查Com口返回的值是否是"BB 31 30 31 34 31 34 39 31 BB"
其中EE和BB应该是数据开始的标志, 真正的值是"06092791"和"10141491", 大概是这个"测试仪"的序列号之类的.
ZY则负责从COM口中读入一个7 bits的数据, 入口参数为对应所连接的Com口, 出口参数(与入口参数共用)为读入的数据(al & 0x7F), (注意: ZY假设ZO已经将COM口设置好了)
这样看来, 调用ZO这部分可以忽略(直接喀嚓), 关键是调用ZY那些地方, 看看读出的数据用来干什么.
能力值:
( LV3,RANK:20 )
9 楼
多谢楼上的这个兄弟,以下附上zy调用部分的源码,看能否指教一二,小狐先谢过了
PARAMETER wmess
PRIVATE val, val0, val1, try
field1 = VARREAD()
SHOW GET (field1) COLOR ,W+/B,
val0 = zyget()
val0 = IIF(val0 > 10, 0, val0)
WAIT WINDOW NOWAIT wmess + '初值' + ;
ALLTRIM(STR(val0))
SET BELL TO 2048, 1
? CHR(7)
SET BELL TO 512, 2
SHOW GET (field1) COLOR ,W+/B,
val1 = val0
val = val1
IF val0 > 110
?? CHR(7)
WAIT WINDOW '接口无效!'
gcomuse = 0
RETURN
ENDIF
try = 1
tryn = 0
DO WHILE (val1<val0+5 .OR. val1> ;
val .OR. tryn<2)
val1 = zyget() * xzz
IF val1 > 80
WAIT WINDOW NOWAIT ;
'退格'
SHOW GET (field1) COLOR , ;
RGB(0,0,255,,,),
?? CHR(7)
RETURN -1
ENDIF
IF val1 > val
val = val1
tryn = 0
ELSE
tryn = tryn + 1
ENDIF
WAIT WINDOW NOWAIT wmess + ;
'初值' + ;
ALLTRIM(STR(val0)) + ;
'测量值' + ;
ALLTRIM(STR(val1))
try = try + 1
SHOW GET (field1) COLOR ,W+/ ;
B,
@ row1,coiumn1 SAY (LOCFILE("人体图库\&pict1","BMP|ICO",;
"Where is &pict1?")) BITMAP SIZE size_h1,size_v1 STYLE "T"
@ row2, coiumn2 TO size_h2, ;
size_v2 STYLE '99' PATTERN ;
1 PEN 1, 8 COLOR RGB(,,, ;
255,0,0)
= INKEY(0.5 , 'H')
@ row1,coiumn1 SAY (LOCFILE("人体图库\&pict2","BMP|ICO",;
"Where is &pict2?")) BITMAP SIZE size_h1,size_v1 STYLE "T"
@ row2, coiumn2 TO size_h2, ;
size_v2 STYLE '99' PATTERN ;
1 PEN 1, 8 COLOR RGB(,,,0, ;
255,0)
SHOW GET (field1) COLOR ,W+/ ;
B,
IF try > 20
bzyin = 'Y'
?? CHR(7)
WAIT TO bzyin WINDOW ;
'是否继续测量(Y/N)?'
IF bzyin $ 'Nn'
SHOW GET (field1) ;
COLOR ,RGB(0, ;
0,255,,,),
gcomuse = 0
RETURN TO main
ELSE
IF bzyin $ 'Yy'
try = 0
ELSE
try = 30
ENDIF
ENDIF
ENDIF
ENDDO
REPLACE (field1) WITH val
SHOW GET (field1)
? CHR(7)
try = 1
DO WHILE (val1<val0-4 .OR. val1> ;
val0+4) .AND. try<8
SHOW GET (field1) COLOR ,W+/ ;
B,
WAIT WINDOW NOWAIT '复位...'
val1 = zyget()
try = try + 1
ENDDO
WAIT CLEAR
SHOW GET (field1) COLOR ,RGB(0,0, ;
255,,,),
xzz = 1
RETURN 1
*
FUNCTION zyget
PRIVATE i, m, m0, m1, m2
i = 0
m0 = CHR(gcom - 1)
m1 = 0
m2 = 0
DO WHILE i<gcomn
m = m0
CALL zy WITH m
m1 = ASC(m)
IF m1 - m2 <= 2 .AND. m1 - ;
m2 >= -2
i = i + 1
IF m1 > m2
m2 = m1
ENDIF
ELSE
m2 = m1
i = 0
ENDIF
= INKEY(gcomt)
ENDDO
RETURN m2
*
能力值:
(RANK: )
10 楼
不知道你是否处理过代码, 单就贴上来的这段代码来看, 从"测量仪"中读取的数据只是用来做为程序流程的控制参数, 同时不断的用类似泡泡的机制将该值显示出来.
你不妨问清楚这个"测量仪"到底是用来"测"什么的吧, 从代码内容以及1200这个波特率来看, 象是医院的多功能自动监控仪, 这个程序的作用是自动收集数据并记录到数据库中备案.
能力值:
(RANK: )
11 楼
突然看到你的要求只是把程序由Foxpro迁移到VFP, 那工作就简单了.
这两个模块的功能我在8楼已经说得很明白了, VFP支持直接调用外部C写的库, 你直接写一个操作 COM 口的库替换它(包括调用方式)就可以了.
能力值:
( LV3,RANK:20 )
12 楼
arab兄弟,请和小狐取得联系好吗,小狐希望得到你的指点
小狐QQ:86074731
能力值:
(RANK: )
13 楼
有事直说.
让我帮忙干活写东西的话就不必说了, 没时间.
有偿也不行.
能力值:
( LV3,RANK:20 )
14 楼
VFP中在gird中怎么才能一敲回车就让光标移到下一行上
我偶然找这个问题,居然发现在国内很我相关的编程论坛上有很多笨人和N条语句来实现这个功能
于是就翻了一下原来的代码,现在贴出来,一句搞定,希望以上的关键词能给pediy增加点人气.
把以下语句直接放到form的loa事件里,这时你在回车时实现的就是下箭头的功能
ON KEY LABEL enter keyboard '{dnarrow}'
能力值:
( LV3,RANK:20 )
15 楼
关于zy.bin
===============================
我用w32asm反汇编合适吗?(原程序为16位汇编)
如果合适,请懂行的兄弟把如下代码给我注释一下,如果不行那就只能用debug了吧
如果用debug,比如我把zy.bin放到d:\,当我输入cmd并输入d:后转到在盘
我再输入debug zy.bin进入debugl界面
然后发u cs:000 50 是可以看到所有16位汇编的代码的,关键是我用debug的什么命令给它的反汇编结果重定向到一个文本文件里,请高手指教。
:00000000 EB01 jmp 00000003
:00000002 90 nop
:00000003 06 push es
:00000004 52 push edx
:00000005 51 push ecx
:00000006 50 push eax
:00000007 1E push ds
:00000008 53 push ebx
:00000009 53 push ebx
:0000000A B910018A07 mov ecx, 078A0110
:0000000F C60700 mov byte ptr [edi], 00
:00000012 3C00 cmp al, 00
:00000014 7411 je 00000027
:00000016 B910003C01 mov ecx, 013C0010
:0000001B 740A je 00000027
:0000001D B900013C02 mov ecx, 023C0100
:00000022 7403 je 00000027
:00000024 B90000BAED mov ecx, EDBA0000
:00000029 0203 add al, byte ptr [ebx]
:0000002B D1EC shr esp, 1
:0000002D 8AE0 mov ah, al
:0000002F F6C401 test ah, 01
:00000032 740A je 0000003E
:00000034 BAE80203D1 mov edx, D10302E8
:00000039 EC in al, dx
:0000003A 247F and al, 7F
:0000003C 8807 mov byte ptr [edi], al
:0000003E 5B pop ebx
:0000003F 5B pop ebx
:00000040 1F pop ds
:00000041 58 pop eax
:00000042 59 pop ecx
:00000043 5A pop edx
:00000044 07 pop es
:00000045 CB retf
能力值:
( LV3,RANK:20 )
16 楼
arab兄弟,能过这两个小程序的分析,可以肯定是用的哪个com口吗?
另外com口读过来的数值一定要经过:"出口参数(与入口参数共用)为读入的数据(al & 0x7F), "这个步骤吗?
我现在想调用mscomm32.ocx读这个com口,读出来还要有你说的那个动作吗?
在线等...
能力值:
( LV3,RANK:20 )
17 楼
最后一次准确的用w32adm反汇编出的两个程序的16位汇编源码:
zy的汇编源码:
:0001.0003 06 push es
:0001.0004 52 push dx
:0001.0005 51 push cx
:0001.0006 50 push ax
:0001.0007 1E push ds
:0001.0008 53 push bx
:0001.0009 53 push bx
:0001.000A B91001 mov cx, 0110
:0001.000D 8A07 mov al , [bx]
:0001.000F C60700 mov byte ptr [bx], 00
:0001.0012 3C00 cmp al, 00
:0001.0014 7411 je 0027
:0001.0016 B91000 mov cx, 0010
:0001.0019 3C01 cmp al, 01
:0001.001B 740A je 0027
:0001.001D B90001 mov cx, 0100
:0001.0020 3C02 cmp al, 02
:0001.0022 7403 je 0027
:0001.0024 B90000 mov cx, 0000
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.0014(C), :0001.001B(C), :0001.0022(C)
|
:0001.0027 BAED02 mov dx, 02ED
:0001.002A 03D1 add dx, cx
:0001.002C EC in al, dx
:0001.002D 8AE0 mov ah, al
:0001.002F F6C401 test ah, 01
:0001.0032 740A je 003E
:0001.0034 BAE802 mov dx, 02E8
:0001.0037 03D1 add dx, cx
:0001.0039 EC in al, dx
:0001.003A 247F and al, 7F
:0001.003C 8807 mov [bx], al
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0032(C)
|
:0001.003E 5B pop bx
:0001.003F 5B pop bx
:0001.0040 1F pop ds
:0001.0041 58 pop ax
:0001.0042 59 pop cx
:0001.0043 5A pop dx
:0001.0044 07 pop es
:0001.0045 CB retf
zo的汇编源码
:0001.0000 EB13 jmp 0015 :0001.0002 90 nop
:0001.0003 EE out dx, al
:0001.0004 30363039 xor [3930], dh
:0001.0008 3237 xor dh, [bx]
:0001.000A 3931 cmp [bx+di], si
:0001.000C EE out dx, al
:0001.000D 3130 xor [bx+si], si
:0001.000F 3134 xor [si], si
:0001.0011 3134 xor [si], si
:0001.0013 3931 cmp [bx+di], si
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.0000(U)
|
:0001.0015 06 push es
:0001.0016 52 push dx
:0001.0017 51 push cx
:0001.0018 50 push ax
:0001.0019 1E push ds
:0001.001A 53 push bx
:0001.001B 53 push bx
:0001.001C B91001 mov cx, 0110
:0001.001F 8A07 mov al , [bx]
:0001.0021 C60700 mov byte ptr [bx], 00
:0001.0024 3C00 cmp al, 00
:0001.0026 7411 je 0039
:0001.0028 B91000 mov cx, 0010
:0001.002B 3C01 cmp al, 01
:0001.002D 740A je 0039
:0001.002F B90001 mov cx, 0100
:0001.0032 3C02 cmp al, 02
:0001.0034 7403 je 0039
:0001.0036 B90000 mov cx, 0000
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.0026(C), :0001.002D(C), :0001.0034(C)
|
:0001.0039 BAEB02 mov dx, 02EB
:0001.003C 03D1 add dx, cx
:0001.003E B080 mov al, 80
:0001.0040 EE out dx, al
:0001.0041 BAE802 mov dx, 02E8
:0001.0044 03D1 add dx, cx
:0001.0046 B060 mov al, 60
:0001.0048 EE out dx, al
:0001.0049 BAE902 mov dx, 02E9
:0001.004C 03D1 add dx, cx
:0001.004E B000 mov al, 00
:0001.0050 EE out dx, al
:0001.0051 BAEB02 mov dx, 02EB
:0001.0054 03D1 add dx, cx
:0001.0056 B003 mov al, 03
:0001.0058 EE out dx, al
:0001.0059 BAEC02 mov dx, 02EC
:0001.005C 03D1 add dx, cx
:0001.005E B003 mov al, 03
:0001.0060 EE out dx, al
:0001.0061 BAE902 mov dx, 02E9
:0001.0064 03D1 add dx, cx
:0001.0066 B000 mov al, 00
:0001.0068 EE out dx, al
:0001.0069 0E push cs
:0001.006A 1F pop ds
:0001.006B BAED02 mov dx, 02ED
:0001.006E 03D1 add dx, cx
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.009E(U)
|
:0001.0070 BE0300 mov si, 0003
:0001.0073 B90A00 mov cx, 000A
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.0079(C), :0001.0086(C)
|
:0001.0076 EC in al, dx
:0001.0077 A820 test al, 20
:0001.0079 74FB je 0076
:0001.007B 83EA05 sub dx, 0005
:0001.007E 8A04 mov al , [si]
:0001.0080 EE out dx, al
:0001.0081 83C205 add dx, 0005
:0001.0084 46 inc si
:0001.0085 49 dec cx
:0001.0086 75EE jne 0076
:0001.0088 B96400 mov cx, 0064
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.009C(C)
|
:0001.008B EC in al, dx
:0001.008C A801 test al, 01
:0001.008E 740B je 009B
:0001.0090 83EA05 sub dx, 0005
:0001.0093 EC in al, dx
:0001.0094 83C205 add dx, 0005
:0001.0097 3CBB cmp al, BB
:0001.0099 7405 je 00A0
* Referenced by a (U)nconditional or (C)onditional Jump at Address:
|:0001.008E(C)
|
:0001.009B 49 dec cx
:0001.009C 75ED jne 008B
:0001.009E EBD0 jmp 0070 * Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.0099(C), :0001.00B4(C), :0001.00BA(C)
|
:0001.00A0 BE0D00 mov si, 000D
:0001.00A3 B90800 mov cx, 0008
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.00A9(C), :0001.00BE(C)
|
:0001.00A6 EC in al, dx
:0001.00A7 A801 test al, 01
:0001.00A9 74FB je 00A6
:0001.00AB 83EA05 sub dx, 0005
:0001.00AE EC in al, dx
:0001.00AF 83C205 add dx, 0005
:0001.00B2 3CBB cmp al, BB
:0001.00B4 74EA je 00A0
:0001.00B6 8A24 mov ah, [si]
:0001.00B8 3AC4 cmp al , ah
:0001.00BA 75E4 jne 00A0
:0001.00BC 46 inc si
:0001.00BD 49 dec cx
:0001.00BE 75E6 jne 00A6
:0001.00C0 B96400 mov cx, 0064
* Referenced by a (U)nconditional or (C)onditional Jump at Addresses:
|:0001.00C6(C), :0001.00D2(C)
|
:0001.00C3 EC in al, dx
:0001.00C4 A820 test al, 20
:0001.00C6 74FB je 00C3
:0001.00C8 83EA05 sub dx, 0005
:0001.00CB B0AA mov al, AA
:0001.00CD EE out dx, al
:0001.00CE 83C205 add dx, 0005
:0001.00D1 49 dec cx
:0001.00D2 75EF jne 00C3
:0001.00D4 5B pop bx
:0001.00D5 5B pop bx
:0001.00D6 1F pop ds
:0001.00D7 58 pop ax
:0001.00D8 59 pop cx
:0001.00D9 5A pop dx
:0001.00DA 07 pop es
:0001.00DB CB retf
希望懂串硬件串口通讯的兄弟能给出注释
能力值:
(RANK: )
18 楼
直接用IDA:
1. IDA认为你要加载的是一个Binary file, 选OK;
2. 接下来会问你要按32位还是16位文件处理, 选No按16位处理;
3. 然后有个提示(可能你已经关了)说加载了Binary file后按"C"可以切换成代码blablabla...的, 直接OK;
4. 进入主界面, 直接到seg0000:0000处按C, 所有代码就都出来了.
下面是关于两个BIN的说明:
ZO.BIN
seg000:0000 seg000 segment byte public 'CODE' use16
seg000:0000 assume cs:seg000
seg000:0000 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
seg000:0000 EB 13 jmp short loc_15
seg000:0002 90 nop
seg000:0003 EE 30+ SendSign db 0EEh, '06092791', 0EEh // 0xEE是开始/结束向对方发送数据标识
seg000:000D 31 30+ RecvSign db '10141491'
seg000:0015 loc_15: ; CODE XREF: seg000:0000
seg000:0015 06 push es // 保存环境
seg000:0016 52 push dx
seg000:0017 51 push cx
seg000:0018 50 push ax
seg000:0019 1E push ds
seg000:001A 53 push bx
seg000:001B 53 push bx
seg000:001C B9 10 01 mov cx, 110h
seg000:001F 8A 07 mov al, [bx] // 取参数: COM口
seg000:0021 C6 07 00 mov byte ptr [bx], 0 // 设返回值
seg000:0024 3C 00 cmp al, 0
seg000:0026 74 11 jz short loc_39 // COM0: CX = 0x110, 0x2E8 + 0x110 = 0x3F8
seg000:0028 B9 10 00 mov cx, 10h
seg000:002B 3C 01 cmp al, 1
seg000:002D 74 0A jz short loc_39 // COM1: CX = 0x10, 0x2E8 + 0x10 = 0x2F8
seg000:002F B9 00 01 mov cx, 100h
seg000:0032 3C 02 cmp al, 2
seg000:0034 74 03 jz short loc_39 // COM2: CX = 0x100, 0x2E8 + 0x100 = 0x3E8
seg000:0036 B9 00 00 mov cx, 0 // COM3: CX = 0x0, 0x2E8 + 0x0 = 0x3E8
// 注意: 下面代码中以0x2E8为标准端口加一个差值做为最终端口, 以上这段代码求的是各COM口对应的端口与标准端口的差值
// 另外, 同一个端口, 在I/O状态下的定义是不同的, 甚至有些端口还依赖于其它端口的设置, 请注意看IDA给的提示.
seg000:0039 loc_39: ; CODE XREF: seg000:0026
seg000:0039 ; seg000:002D
seg000:0039 ; seg000:0034
seg000:0039 BA EB 02 mov dx, 2EBh // 0x2EB = 0x2E8 + 3, 其中0x2E8是基址, +3是line control register
seg000:003C 03 D1 add dx, cx // 注意: 这里加上CX后就是对应的实际端口值
seg000:003E B0 80 mov al, 80h // 设置了最高位, 即进入DLAB (Divisor Latch Access Bit)
seg000:0040 EE out dx, al ; COM: line control register bits:
seg000:0040 ; 0-1: word length: 00=5, 01=6, 10=7, 11=8
seg000:0040 ; 2: stop bits: 0=1,1=2
seg000:0040 ; 3-4: parity: x0=None, 01=Odd, 11=Even
seg000:0040 ; 5: stuck parity
seg000:0040 ; 6: enable break control. 1=start sending 0s (spaces)
seg000:0040 ; 7: DLAB (Divisor Latch Access Bit)
seg000:0041 BA E8 02 mov dx, 2E8h // 0x2E8 = 0x2E8 + 0, 当DLAB生效时, +0是divisor latch low byte
seg000:0044 03 D1 add dx, cx // 注意: 这里加上CX后就是对应的实际端口值
seg000:0046 B0 60 mov al, 60h // 低字节是0x60
seg000:0048 EE out dx, al ; COM: transmitter holding register
seg000:0048 ; or (when DLAB=1) divisor latch low byte.
seg000:0049 BA E9 02 mov dx, 2E9h // 0x2E9 = 0x2E8 + 1, 当DLAB生效时 +1是divisor latch high byte
seg000:004C 03 D1 add dx, cx // 注意: 这里加上CX后就是对应的实际端口值
seg000:004E B0 00 mov al, 0 // 高字节是0x00
seg000:0050 EE out dx, al ; COM: divisor latch high byte(when DLAB=1)
seg000:0050 ; or interrupt enable register bits:
seg000:0050 ; 0:1=an interrupt when rec'd data is available
seg000:0050 ; 1:1=interrupt when transmit buffer is empty
seg000:0050 ; 2:1=int on rec'r line status (error or break)
seg000:0050 ; 3:1=int on modem status (CTS,DSR,RI,RLSD)
// 以上代码实现了将COM口设置成1200 bps (divisor latch = 0x0060)
seg000:0051 BA EB 02 mov dx, 2EBh // 0x2EB = 0x2E8 + 3, +3是line control register
seg000:0054 03 D1 add dx, cx // 注意: 这里加上CX后就是对应的实际端口值
seg000:0056 B0 03 mov al, 3 // 最高位清0, 即取消DLAB, 同时低两位为3, 其它们为0, 即8N1
seg000:0058 EE out dx, al ; COM: line control register bits:
seg000:0058 ; 0-1: word length: 00=5, 01=6, 10=7, 11=8
seg000:0058 ; 2: stop bits: 0=1,1=2
seg000:0058 ; 3-4: parity: x0=None, 01=Odd, 11=Even
seg000:0058 ; 5: stuck parity
seg000:0058 ; 6: enable break control. 1=start sending 0s (spaces)
seg000:0058 ; 7: DLAB (Divisor Latch Access Bit)
seg000:0059 BA EC 02 mov dx, 2ECh // 0x2EC = 0x2E8 + 4, +4是modem control register
seg000:005C 03 D1 add dx, cx // 注意: 这里加上CX后就是对应的实际端口值
seg000:005E B0 03 mov al, 3 // 激活DTR (data termnl ready)和RTS (request to send), 准备收发数据
seg000:0060 EE out dx, al ; COM: modem control reg bits:
seg000:0060 ; 0: 1=activate -DTR (-data termnl ready), 0=deactivate
seg000:0060 ; 1: 1=activate -RTS (-request to send), 0=deactivate
seg000:0060 ; 2: 1=activate -OUT1 (spare, user-designated output)
seg000:0060 ; 3: 1=activate -OUT2
seg000:0060 ; 4: 1=activate loopback for diagnostic testing
seg000:0061 BA E9 02 mov dx, 2E9h // 0x2E9 = 0x2E8 + 1, +1是interrupt enable register
seg000:0064 03 D1 add dx, cx // 注意: 这里加上CX后就是对应的实际端口值
seg000:0066 B0 00 mov al, 0 // 禁用COM口中断, 即COM口不产生硬件中断
seg000:0068 EE out dx, al ; COM: divisor latch high byte(when DLAB=1)
seg000:0068 ; or interrupt enable register bits:
seg000:0068 ; 0:1=an interrupt when rec'd data is available
seg000:0068 ; 1:1=interrupt when transmit buffer is empty
seg000:0068 ; 2:1=int on rec'r line status (error or break)
seg000:0068 ; 3:1=int on modem status (CTS,DSR,RI,RLSD)
// 初始化完毕, 接下来准备发数据
seg000:0069 0E push cs
seg000:006A 1F pop ds
seg000:006B BA ED 02 mov dx, 2EDh // 0x2ED = 0x2E8 + 5, +5是line status register
seg000:006E 03 D1 add dx, cx // 注意: 这里加上CX后就是对应的实际端口值
// 因为下面需要使用到cx, 所以这时dx固定成dx+cx的值, 然后根据需要直接对dx进行增减操作
seg000:0070 loc_70: ; CODE XREF: seg000:009E
seg000:0070 BE 03 00 mov si, offset SendSign // 要发送的数据
seg000:0073 B9 0A 00 mov cx, 0Ah // 长度
seg000:0076 loc_76: ; CODE XREF: seg000:0079
seg000:0076 ; seg000:0086
seg000:0076 EC in al, dx ; COM: line status register bits:
seg000:0076 ; 0: 1=data ready (DR)
seg000:0076 ; 1: 1=overrun error (OE)
seg000:0076 ; 2: 1=parity error (PE)
seg000:0076 ; 3: 1=Bad stop bit in character
seg000:0076 ; 4: 1=break indicated (BI)
seg000:0076 ; 5: 1=transmitter holding register empty
seg000:0076 ; 6: 1=transmitter empty
seg000:0077 A8 20 test al, 20h
seg000:0079 74 FB jz short loc_76 // 检查COM口的状态寄存器, 直到bit5即transmitter holding register empty为真
// COM口说计算机可以发送数据给它
seg000:007B 83 EA 05 sub dx, 5 // 0x2ED - 5 = 0x2E8 + 0, +0是transmitter holding register
seg000:007E 8A 04 mov al, [si] // 取当前数据并发送
seg000:0080 EE out dx, al ; COM: transmitter holding register
seg000:0080 ; or (when DLAB=1) divisor latch low byte.
seg000:0081 83 C2 05 add dx, 5 // 恢复为line status register
seg000:0084 46 inc si // 下一个数据
seg000:0085 49 dec cx // 计数减1
seg000:0086 75 EE jnz short loc_76 // 循环直到10个字节全部发送完毕
// OK, 10个字节全部发送完毕
seg000:0088 B9 64 00 mov cx, 64h // 尝试100次
seg000:008B loc_8B: ; CODE XREF: seg000:009C
seg000:008B EC in al, dx ; COM: line status register bits:
seg000:008B ; 0: 1=data ready (DR)
seg000:008B ; 1: 1=overrun error (OE)
seg000:008B ; 2: 1=parity error (PE)
seg000:008B ; 3: 1=Bad stop bit in character
seg000:008B ; 4: 1=break indicated (BI)
seg000:008B ; 5: 1=transmitter holding register empty
seg000:008B ; 6: 1=transmitter empty
seg000:008C A8 01 test al, 1
seg000:008E 74 0B jz short loc_9B // 检查COM口的状态寄存器, 直到bit0即data ready(DR)为真
// COM口说有数据要发给计算机
seg000:0090 83 EA 05 sub dx, 5 // 0x2ED - 5 = 0x2E8 + 0, +0是receiver buffer register
seg000:0093 EC in al, dx ; COM: receiver buffer register.
seg000:0093 ; 8 bits of character received.
seg000:0094 83 C2 05 add dx, 5 // 恢复为line status register
seg000:0097 3C BB cmp al, 0BBh // 读到的是0xBB吗? 0xBB是对方开始/结束发送数据标识
seg000:0099 74 05 jz short loc_A0
seg000:009B
seg000:009B loc_9B: ; CODE XREF: seg000:008E
seg000:009B 49 dec cx
seg000:009C 75 ED jnz short loc_8B // 不是, 计数器减1, 循环
seg000:009E EB D0 jmp short loc_70 // 100次了, 重新发送SendSign
// 谢天谢地, 终于收到了一个0xBB
seg000:00A0 loc_A0: ; CODE XREF: seg000:0099
seg000:00A0 ; seg000:00B4
seg000:00A0 ; seg000:00BA
seg000:00A0 BE 0D 00 mov si, offset RecvSign // 应该收到的数据
seg000:00A3 B9 08 00 mov cx, 8 // 长度
seg000:00A6 loc_A6: ; CODE XREF: seg000:00A9
seg000:00A6 ; seg000:00BE
seg000:00A6 EC in al, dx ; COM: line status register bits:
seg000:00A6 ; 0: 1=data ready (DR)
seg000:00A6 ; 1: 1=overrun error (OE)
seg000:00A6 ; 2: 1=parity error (PE)
seg000:00A6 ; 3: 1=Bad stop bit in character
seg000:00A6 ; 4: 1=break indicated (BI)
seg000:00A6 ; 5: 1=transmitter holding register empty
seg000:00A6 ; 6: 1=transmitter empty
seg000:00A7 A8 01 test al, 1
seg000:00A9 74 FB jz short loc_A6 // 检查COM口的状态寄存器, 直到bit0即data ready(DR)为真
seg000:00AB 83 EA 05 sub dx, 5
seg000:00AE EC in al, dx ; COM: receiver buffer register.
seg000:00AE ; 8 bits of character received.
seg000:00AF 83 C2 05 add dx, 5
seg000:00B2 3C BB cmp al, 0BBh
seg000:00B4 74 EA jz short loc_A0 // 又读到0xBB? 重来
seg000:00B6 8A 24 mov ah, [si] // 当前应该读到的数据
seg000:00B8 3A C4 cmp al, ah
seg000:00BA 75 E4 jnz short loc_A0 // 不一样, 重来
seg000:00BC 46 inc si
seg000:00BD 49 dec cx
seg000:00BE 75 E6 jnz short loc_A6 // OK, 下一个, 直接读到RecvSign一样的数据
// OK, 接上头了
seg000:00C0 B9 64 00 mov cx, 64h // 再来100次
seg000:00C3 loc_C3: ; CODE XREF: seg000:00C6
seg000:00C3 ; seg000:00D2
seg000:00C3 EC in al, dx ; COM: line status register bits:
seg000:00C3 ; 0: 1=data ready (DR)
seg000:00C3 ; 1: 1=overrun error (OE)
seg000:00C3 ; 2: 1=parity error (PE)
seg000:00C3 ; 3: 1=Bad stop bit in character
seg000:00C3 ; 4: 1=break indicated (BI)
seg000:00C3 ; 5: 1=transmitter holding register empty
seg000:00C3 ; 6: 1=transmitter empty
seg000:00C4 A8 20 test al, 20h
seg000:00C6 74 FB jz short loc_C3 // 检查COM口的状态寄存器, 直到bit5即transmitter holding register empty为真
// COM口说计算机可以发送数据给它
seg000:00C8 83 EA 05 sub dx, 5
seg000:00CB B0 AA mov al, 0AAh // 发送0xAA, 通知设备开始工作?
seg000:00CD EE out dx, al ; COM: transmitter holding register
seg000:00CD ; or (when DLAB=1) divisor latch low byte.
seg000:00CE 83 C2 05 add dx, 5
seg000:00D1 49 dec cx
seg000:00D2 75 EF jnz short loc_C3 // 100次啊100次
seg000:00D4 5B pop bx
seg000:00D5 5B pop bx
seg000:00D6 1F pop ds
seg000:00D7 58 pop ax
seg000:00D8 59 pop cx
seg000:00D9 5A pop dx
seg000:00DA 07 pop es
seg000:00DB CB retf // 恢复环境后返回
seg000:00DB seg000 ends
ZY.BIN
seg000:0000 seg000 segment byte public 'CODE' use16
seg000:0000 assume cs:seg000
seg000:0000 assume es:nothing, ss:nothing, ds:nothing, fs:nothing, gs:nothing
seg000:0000 EB 01 jmp short loc_3
seg000:0002 90 nop
seg000:0003
seg000:0003 loc_3: ; CODE XREF: seg000:0000
seg000:0003 06 push es // 保存环境
seg000:0004 52 push dx
seg000:0005 51 push cx
seg000:0006 50 push ax
seg000:0007 1E push ds
seg000:0008 53 push bx
seg000:0009 53 push bx
seg000:000A B9 10 01 mov cx, 110h
seg000:000D 8A 07 mov al, [bx] // 取参数: COM口
seg000:000F C6 07 00 mov byte ptr [bx], 0 // 设返回值
seg000:0012 3C 00 cmp al, 0
seg000:0014 74 11 jz short loc_27 // COM0: CX = 0x110, 0x2E8 + 0x110 = 0x3F8
seg000:0016 B9 10 00 mov cx, 10h
seg000:0019 3C 01 cmp al, 1
seg000:001B 74 0A jz short loc_27 // COM1: CX = 0x10, 0x2E8 + 0x10 = 0x2F8
seg000:001D B9 00 01 mov cx, 100h
seg000:0020 3C 02 cmp al, 2
seg000:0022 74 03 jz short loc_27 // COM2: CX = 0x100, 0x2E8 + 0x100 = 0x3E8
seg000:0024 B9 00 00 mov cx, 0 // COM3: CX = 0x0, 0x2E8 + 0x0 = 0x3E8
// 注意: 下面代码中以0x2E8为标准端口加一个差值做为最终端口, 以上这段代码求的是各COM口对应的端口与标准端口的差值
seg000:0027 loc_27: ; CODE XREF: seg000:0014
seg000:0027 ; seg000:001B
seg000:0027 ; seg000:0022
seg000:0027 BA ED 02 mov dx, 2EDh // 0x2ED = 0x2E8 + 5, 其中0x2E8是基址, +5是line status register
seg000:002A 03 D1 add dx, cx // 注意: 这里加上CX后就是对应的实际端口值
seg000:002C EC in al, dx ; COM: line status register bits:
seg000:002C ; 0: 1=data ready (DR)
seg000:002C ; 1: 1=overrun error (OE)
seg000:002C ; 2: 1=parity error (PE)
seg000:002C ; 3: 1=Bad stop bit in character
seg000:002C ; 4: 1=break indicated (BI)
seg000:002C ; 5: 1=transmitter holding register empty
seg000:002C ; 6: 1=transmitter empty
seg000:002D 8A E0 mov ah, al
seg000:002F F6 C4 01 test ah, 1
seg000:0032 74 0A jz short loc_3E // 检查COM口的状态寄存器, 直到bit0即data ready(DR)为真
seg000:0034 BA E8 02 mov dx, 2E8h // 0x2E8 = 0x2E8 + 0, +0是receiver buffer register
seg000:0037 03 D1 add dx, cx // 注意: 这里加上CX后就是对应的实际端口值
seg000:0039 EC in al, dx ; COM: receiver buffer register.
seg000:0039 ; 8 bits of character received.
seg000:003A 24 7F and al, 7Fh
seg000:003C 88 07 mov [bx], al // 读一个字节, 去掉最高位后存到返回值的地址上
seg000:003E loc_3E: ; CODE XREF: seg000:0032
seg000:003E 5B pop bx
seg000:003F 5B pop bx
seg000:0040 1F pop ds
seg000:0041 58 pop ax
seg000:0042 59 pop cx
seg000:0043 5A pop dx
seg000:0044 07 pop es
seg000:0045 CB retf // 恢复环境后返回
seg000:0045 seg000 ends
能力值:
(RANK: )
19 楼
COM口由VFP里的全局变量 gcom 决定. 看你7楼的代码, 应该是COM1.
原始代码里有这个操作(参考ZY.BIN的003A处的代码), 我也不知道为什么.
你自己决定.
无用功.
能力值:
( LV3,RANK:20 )
20 楼
谢arab,分析的很详细,正在由另一外兄弟写这个的dll在硬件上测试呢.
能力值:
( LV2,RANK:10 )
21 楼
只要有市场,就有生命力。