| 网站首页 | 业界新闻 | 小组 | 威客 | 人才 | 下载频道 | 博客 | 代码贴 | 在线编程 | 编程论坛
欢迎加入我们,一同切磋技术
用户名:   
 
密 码:  
共有 19165 人关注过本帖
标题:大家来玩玩这道题!
只看楼主 加入收藏
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
结帖率:100%
收藏
已结贴  问题点数:20 回复次数:8 
大家来玩玩这道题!
在一个论坛看见这条问题:-

在masm里面可以写
and al,11000101B
在debug模式的-a状态下,如何输入2进制(以B结尾)的数字?


标准的回答是:debug不支持!

恩,或许是有的,但就我所见几款debug都不支持b(2进制)或者d(10进制)的后缀。
有没有办法令debug支持呢?
若有debug源码,功力和时间许可,这是有可能的。

我有一份某位外国大牛写的debug源码,基本上没瞄过,看看上千万行的代码就却步了。

想了一下,不修改源码仍然可以实作吧。终于花了1天,写了一个小程式,它先载入或debug.exe
然后在背后等待,只要使用者输入

mov eax,1234567890d  (任意) 或
mov ebx,1001001010101010110000111b  (任意) 

然后按一下F10键,原值会立即转成16进制值。
若没有b或d的后缀,或者输入的不是合法的10进制或2进制值,按了F10也不会鸟它。
就这样:

输入10进制

图片附件: 游客没有浏览图片的权限,请 登录注册


按了F10后,又输入2进制

图片附件: 游客没有浏览图片的权限,请 登录注册



按了F10后

图片附件: 游客没有浏览图片的权限,请 登录注册


这题我写了500行代码,不算很长,大家可以玩玩这题,讲讲想法,可能会更精简些。
晚些我会发代码和说说做法。


这是程式,含小程式和两款debug,按dbug即可,大家可以试试有没有bug。
下载
http://wendix2017.


其实只要就够了,这debug版本比原debug多了些功能,按?有help, rx 转换成32bit模式,
可以直接输入mov eax,1234567...push dword ptr [ebx]等32bit暂存器指令。

[此贴子已经被作者于2016-7-10 17:44编辑过]

搜索更多相关主题的帖子: 如何 
2016-07-07 15:41
wmf2014
Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19Rank: 19
等 级:贵宾
威 望:216
帖 子:2039
专家分:11273
注 册:2014-12-6
收藏
得分:10 
win32下控制台还能做内存驻留程序吗?纯dos下做过。

能编个毛线衣吗?
2016-07-07 17:15
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
回复 2楼 wmf2014
win32控制台属于windows,程式都是ring3的大环境,并不须要dos的驻留手法。



[此贴子已经被作者于2016-7-7 19:31编辑过]

2016-07-07 18:57
zhulei1978
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:53
帖 子:1351
专家分:1200
注 册:2006-12-17
收藏
得分:10 
想不出来,不内存驻留怎么做

其实我就是改变社会风气,提高少女素质,刺激电影市道,提高年轻人内涵,玉树临风,风度翩翩的整蛊专家,我名叫古晶,英文名叫JingKoo!
2016-07-07 20:08
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
回复 4楼 zhulei1978
不必用int21,ah=31h或int27h的驻留方式,拦截了int9h,载入程式但本身并不退出,然后等待f10,再看看有没有合法输入,不一定要mov ax, 1234d的指令,只要是一个完整的数字串包含d或b的后缀即可,例如
push word 12345d  [按10]
push 80d  [按10] 
push 11001100b  [按10]
mov dword ptr [bx], 98765d  [按10]
f  ds:200 L 2000d   [按10]
e ds:200 100d  [按10]
另一个例子
h 1234d [按10] 变了 h 4d2 后 h 4d2 345d [按10] 变 h 04D2 0159 [按回车]得062B 0379 
这样相等于10进制的 1234和345相加相減的16进制结果

(2016/7/8)
新增以h为后缀的功能,使用方法,例如:
mov  ax, 2000   输入后,却想知道2000这16进制10制是多少,加多一个h
mov  ax, 2000h  [按f10] ,变成 mov ax,8192D,D表示10进制,换算后再按一下f10,
因有D的后缀,变回mov  ax, 2000

一如上面的例子,任何合法的数字符串均可转换,如
push word ptr abcdh
mov dword ptr [di], 1234FFFFh

新增载入执行档功能,用法:
Bbug [执行档名] [参数(如有)]
例如:bdug test.asm
载入 (dos编辑程式)并以test.asm为参数,会认为test.asm是本身的参数。
在 [载入程式] 中,可用f10作进制转换,用法和debug一样
图片附件: 游客没有浏览图片的权限,请 登录注册

按f10后,12345d会转成3039





程式更新了,请重新下载
http://wendix2017.

[此贴子已经被作者于2016-7-10 17:44编辑过]

2016-07-08 08:11
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
今天有空,先说说程式流程。

和windows的并行观念不同,在dos中,同一时间只能有一个程式运行,要躲在背后监视,人们会想到驻留,驻留是程式完结时不用int21,ah=4ch等正常手段,而是int21h,ah=31h或int27h,这两种方式主要是不释放内存,程式某部份被dos保留,亦即驻留。程式至少要有一个被唤醒的机制,驻留前需做一些必要的中断修改,int9, int8, int1ch, int16h,int21h等等是常被拦截的中断,等到驻留部份被触动,再检查条件是否符合,若是则做动作。

回到这个程式,既然针对debug,其实不必驻留,只要拦截适当的中断,载入主程式,然后等待按键,符合则做事,主程式完结了,这个程式也结束了。

程式流程:

1.修改自身程式的内存分配(int21h,4Ah),缩减到仅可运作为止,释放内存用以载入新程式。

2.修改中断int9h(键盘中断)和int1ch(时脉中断),指向新的中断代码。

3.载入debug(int 21h, ah=4bh, ds:dx指向程式名称)。

4.成功载入后,loader部份已完成任务,以下是新键盘中断int9的事了。

5.在debug中,若使用者输入 mov ax, 1234d ,再按f10。

6.新的int9被触动,由port 60h查到(不是读走)按键(int al,60h,),查知是否f10,是继续,不是离开。

7.读取当前光标位置,通常在d之后,由这位置开始.....

8.读取光标位置的字符,记录在一个字符串中,光标前进一位,回到7。

9.直到读入字符是[,]或[空白],或光标到达该列的[行坐标0]。

10.检查字符串是否以d,b,h作 [唯一后缀],排除所有不符组合,如1233hb, abcb等。

11.根据d,b,h呼叫相关的子程序,将输入数字符串转成32bit或16bit的16进制值(若后缀为h,则转10进制),比如使用者输入 mov ax,1234d,转换后得一16进值04D2。

12.目的已达成一半,我们有了04D2,直接输出04D2到屏幕?不对,debug不可能知道屏幕上的1234被偷换了。想想,它必然是透过int 16h或int21h,ah=0ah或者别的什么读键函读取输入,而不会像我们这个幕后者在屏幕抓取,对不?

13.好吧,我们模拟原来的输入方法,比如 mov ax,1234d,我们把退位键的扫瞄码(0eh)放ch,ASCII码(08h)放cl, 利用int 16h,ah =5,放回键盘缓冲。平常读取键值是int16h,ah=0,ah =5却是逆操作,置放键值。 [,1234d]一共五次退位(backspace)到[,]为止,然后是04D2的每一字符的键值,经查表(早准备好,就是0-F的扫瞄码和ASCII码),将04D2的键值透过int16,ah=5输出。在debug而言,使用者的动作是键入mov ax,1234d后,再打5次退位,然后键入04D2!

14.成功了吗?不是,仍远啊.......我们忽略了一个限制,bios的键盘缓冲最多能容纳15个字符。大家应该有经验,某些反应慢的程式,若输入太快或按着某键不放就会发出beep声,表示键盘缓冲已满,满了后的输入会被漏掉。

15.假若我们输入mov eax, 1234567890d_ 或mov ax, 1234d [无耻的30个空白]_
由光标位置[_]到[,]的退位,再加上输出的16进位值,那个小得可怜的15个键盘缓冲无论如何放不下,多了的就丢失了。于是我们招来int1ch时脉中断帮帮忙。先不忙送出按键,我们把输出按键的码值依次放入一个 [按键等待串列]中备用,送完后设定一个变数(sendFlag=1),用以唤醒int1ch工作,工作到这里int9跑去休息了。

16.Int1c正式登场!严格的说,int8才是时脉中断,cpu每1/18秒呼叫一次int8,做一些例行工作。而int8的代码中,总有一条是int1ch,int1ch原来代码中只有一条指令,iret,即不作事返回。

17.之前,我们拦截了int1ch,每次新的int1ch被呼叫,首先检查sendFlag=?,若0则不作事返回,若1则是工作的时候了!首先检查键盘缓冲是否仍有按键,有则离开,确定没有后,读入[按键等待串列]到cx,利用int16h,ah=5,送出,直到15次后,若仍未送完,不忙,留待下一次,离开.......若按键太多,int1ch可能要分多次才送完,直到[按键等待串列]读到0,才算完成工作,标志sendFlag设回0,重新唤醒int9做事(一天仍有按键未送完,即使按了f10,int9也不鸟你,以防止重复呼叫)。

18.呼,忙完了,等待下次f10吧。



原理说完,留下来是码字和细节处理,程式不会很难,考验的除错毅力和耐性而已。

[此贴子已经被作者于2016-7-10 17:45编辑过]

2016-07-10 10:43
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
以下是代码,有问题欢迎提出讨论

程式是com格式
masm 5.x
masm dbug.asm
link dbug.asm
exe2bin dbug.exe

masm6.x
ml/AT dbug.asm

程序代码:
.286
scan_key    equ    44h    ;f10
        cseg    segment
        assume     cs:cseg,ds:cseg,es:cseg
        org    100h
begin:        jmp    INIT

OLD09_OFF        DW    0
OLD09_SEG        DW    0
old1C_off        dw    0
old1C_seg        dw    0
main_file        db    '',0
main_file1        db    'debug.exe',0
keep_ss            dw    0
keep_sp            dw    0
pcb                dw    0,12 dup (0)
align 2
SendBuffer        db    (80 + 20)*2 dup (0)
OverwriteStr    db     16 dup (0)    ;max FFFF FFFF
lineBuffer        db    82 dup (0)  ;1 line
clear_len        equ $ - offset SendBuffer
HexprocTable    dw    offset BtoH,offset DtoH,offset HtoD
Lastpos            dw    0
firstpos        dw    0
startpos        dw    0
hexTable         db     '0123456789ABCDEF'
hex_table       db          08,22,'084C2A6E195D3B7Fabcdef' ;max,comp lenght,data
work_flag        db    0    ;int9工作中标志
work_flag1        db    0    ;int1ch工作中标志
userinput        dd    0
ScanTable        db  30h,0bh,31h,02h,32h,03h,33h,04h,34h,05h,35h,06h,36h,07h,37h,08h
                db  38h,09h,39h,0ah,41H,1EH,42H,30H,43H,2EH,44H,20H,45H,12H,46H,21H
Sendflag        db    0
;SendCount        dw    0
LastSendAddr    dw    0
argc             db    0
argv             dw     5 dup (?)
userprogram        db    60 dup (0)
;------------------------------------------------------------------------------
NEW_INT09:          
        STI
        pushf
        push    ax
        cmp     cs:work_flag,0    ;工作中?
        jnz     not_key        ;对,走
        in      al,060h        
        push    ax
        in      al,061h
        or      al,080h
        out     061h,al
        and     al,07fh
        out     061h,al
        mov     al,020h
        out     020h,al
        pop     ax
        cmp     al,scan_key    ;是否约定键
        jnz        not_key        ;
        cmp        sendFlag,1        ;送完key没?
        jz        not_key        ;未完,不处理
        mov     cs:work_flag,1    ;设定工作中标志
        call    mainhex        ;主程序
        mov     cs:work_flag,0    ;清除工作中标志
        pop     ax
        popf
        iret    ;直接返回
not_key:pop     ax
        popf
        jmp     dword ptr cs:old09_off    ;返回原来int9
;------------------------------------------------------------------------------
mainhex:push    ds
        push    es
        pusha
        mov        ax,cs
        mov        ds,ax
        mov        es,ax

        ;------    初始化 开始-----
        xor        bp,bp
        mov     word ptr userinput,bp
        mov     word ptr userinput+2,bp
        cld
        mov        di,offset SendBuffer
        mov        al,0
        mov     cx,clear_len    ;SendBuffer 至 lineBuffer
        rep        stosb        ;完后di指向lineBuffer尾
        ;------    初始化 完结-----

        sub        di,2        ;指向lineBuffer尾之前2bytes
        mov     cx,80        ;最长一列80bytes
        ;mov     bx,0
        call    GetCur    ;get cursor posion , dh=row, dl=column
        mov     Lastpos,dx ;光标最后位置        
        mov        bl,0     ;D和B的累加,初始化        

m10:    call    SetCurPos ;设定光标位置        
        call    GetChAtr    ;读取该位置字节(al)
        mov     ah,al
        cmp     ah,','    ; 是否[,]
        jz        m60    ;是则找到源头
        cmp     ah,20h    ;空白?
        jnz        m15    ;不是
        or        bl,bl    ;bl是否0    
        jnz        m60    ;bl不是0,即找到d或b后的第一空白

m15:    and        ah,5fh    ;转大写
        cmp     ah,'D'    ;D ?
        jnz        m20    ;
        or      bp,2    ;D则设定BIT1
        jmp        short m25

m20:    cmp     ah,'H'    
        jnz        m22
        or         bp,4    ;H则设定BIT2
        jmp        short m26

m22:    cmp     ah,'B'    ;是否B
        jnz        m30    ;
        or      bp,1h    ;B则设定BIT0

m25:    test    bp,4    ;是否有h
        jnz        m28    ;有,跳过al不设0
m26:    mov        al,0    ;B或D到此,AL设0,用以清除该D或B的字符
m28:    ; h , d , b到此
        cmp        byte ptr [di+1],20h
        jz        m29
        cmp        byte ptr [di+1],0
        jz        m29    ;jmp m100
        test    bp,4    ;是否有h ;和上面代码重复,未修正!
        jz        m35    ;没有h,不许有其他字符在后

m29:    ;h , d, b之后必须为空白或0,否则离开
        inc     bl    ;累加D或B或H

m30:    mov        [di],al    ;清除该D或B或H的字符
        dec        di    ;缓冲移前一位
        dec        dl    ;光标移前一位
        jns        m40    ;若DL=0(光标位置0,再减则负)
m35:    jmp        m100    ;过了头,仍找不到[,] 走
m40:    loop    m10    ;下一字符

m60:    ;到了[,]或空白位置
        test     bp,0000000000000100b ;是否有H
        jz        m61    ;
        mov     bp,0000000000000100B ;给值4
        jmp        short m62    ;不比较BL个数(可能有B,D等16进制的字符)

m61:    dec     bl    ;若只有1个b或b,bl=1,dec bl,等于0则输入正常
        jnz        m100

m62:    inc        dl
        mov     firstpos,dx  ;[,]之后的光标位置
        mov     ax,Lastpos   
        sub        ax,dx
        dec        ax
        jz        m100     ;[,]之后没有字符
        inc        di    ;退回[,]之后
        mov        startpos,di    ;此为字符串起点
        dec        bp    ;若数字符后只有B或D或H,则BP=1,2或3,减1后0则不符
        js        m100    ;没有D或B   100  010 001 011 减后 011 001 000 
        cmp     bp,2    ;2 ?
        jb        m64    ;0,1都ok
        jz        m100    ;=2, d和b并存又没有h
        mov     bp,2    ;置值
m64:    ;     bp=0 (b)or 1(d) or 2(h)
        shl     bp,1       ;根据BP(0或2)跳至2进位转16进位或10进位转16进位的子程序
        call    word ptr cs:HexprocTable[bp]
        jc        m100    ;错误,回存光标,离开

        ;以下输出到键盘缓冲
        mov     dx,Lastpos        ;回到按F10时的光标位置
        call    SetCurPos        ;
        mov        bp,Lastpos        ;最后位置
        sub     bp,firstpos        ;减[,]后位置
        ;mov    SendCount,bp    ;退位(backspace)数

        ;----送至my key buffer起--
        mov     di,offset SendBuffer   ;指向键盘缓冲(准备送出)
        mov     cx,bp        ;退位(backspace)数
        mov        ah,0eh        ;backspace 扫瞄码
        mov        al,08h        ;backspace ASCII码
        rep        stosw        ;送出cx个

        mov        si,offset OverwriteStr    ;16进制的字符串
        mov        bx,di        ;backspace扫瞄码之后
m65:
        lodsb            ;读入
        or        al,al        ;是否0
        jz        m68        ;是,走
        mov        di,offset hexTable     ;16进表格
        mov        cx,16        ;0-F
        repnz    scasb        ;找按键
        sub        di,offset hexTable +1  ;哪一个
        shl        di,1
        mov     ax,word ptr ScanTable[di] ;根据16位字节,取scancode和ascii
        mov        [bx],ax        ;
        add        bx,2        ;下一个
        ;inc    SendCount        ;累加个数
        jmp        short m65        ;下一个
        ;----送至my key buffer完--

m68:    mov     sendFlag,1        ;启动送key标志
        mov        ax,offset SendBuffer 
        mov        LastSendAddr,ax    ;初始化最后地址
        ;call    Sendkey        ;离开,int9不做送key,由int1ch做

m90:    popa
        pop    es
        pop    ds
        ret

m100:    mov        dx,Lastpos       ;不符要求,回存光标位置,离开
        call    SetCurPos
        jmp        short m90

;------------------------------------------------------------------------------
; 送出键值到键盘缓冲,每次15个,未完下次再送,直到完送.
Sendkey:push    ds
        push    es
        pusha
        mov     ax,cs
        mov        ds,ax
        xor        ax,ax
        mov     es,ax
        mov     si,041Ah        ;键盘缓冲区开头位址
        mov     ax,es:[si]        ;041A,键盘缓冲区开头位址
        cmp     ax,es:[si+2]    ;041C,键盘缓冲区结束位址
        jnz        send90        ;不相同,即缓冲区仍有键值未清,走
        mov        si,LastSendAddr
        mov     di,15        ;一次送15key
send10:        
        mov        cx,[si]
        jcxz    send20        ;送完了,走
        mov     ah,5        ;送出按键
        int        16h
        add        si,2        ;下一个
        dec        di        ;15完了?
        jnz        send10        ;
        mov        LastSendAddr,si    ;送完15键,但全数未完,保存最后key地址,下次用
        jmp     short send90    ;送完15key,走

send20:    ;送完全部按键
        mov     sendflag,0        ;清除

send90:    popa
        pop        es
        pop        ds
        ret
;------------------------------------------------------------------------------
HtoD:    call    FindNonSpace
        jz        HtoDx ;找不到空白之外的字符
        ;si = first byte
        call    htoh    ;dx:ax返回hex值
        jc        HtoDx    ;错误,走
        mov     word ptr userinput,ax
        mov     word ptr userinput+2,dx
        mov        di,offset OverwriteStr
        call    print_dec  ;out dx:ax(dec) to es:di
        mov     al,'D'
        stosb
        mov        al,0
        stosb
        clc    
        ret
HtoDx:    stc
        ret
;------------------------------------------------------------------------------
;output DX:AX,dword (0-FFFFFFFFh / 0-4294967295)  ;印出32BIT数值子程序
print_dec:
        xor     cx,cx
        xchg     bp,dx
        mov     si,10 ;div by 10
        mov     bx,30h
print_dec1:
        or         bp,bp
        jz         print_dec3
        xchg     bp,ax
        xor     dx,dx
        div     si
        xchg     bp,ax
        div     si
        or         dl,bl
        push     dx
        inc     cx
        jmp     short print_dec1
print_dec3:
        xor     dx,dx
        div     si
        or         dl,bl
        push     dx
        inc     cx
        or         ax,ax
        jnz     print_dec3
print_dec4:
        pop     ax
        stosb
        loop     print_dec4
        ret
;------------------------------------------------------------------------------
;转值子程序,把输入的10进制文字转成16进制
;输入:ds:si数字字符串起点,以0dh结束
;输出:ax=转换后的16进制值,cf=1表示有非数字字符
.386
GetValue:
        push     ebx
        push     edi
        xor     ebx,ebx
        mov     edi,10
GetV10:         lodsb     ;指向起点
        and     eax,000000ffh ;清除高bit,保留AL
        cmp     al,0  ;-----zero
        jz         Getvx
        sub     al,'0'
        cmp     al,9
        ja         Getvy
        xchg     ebx,eax  ;交换
        mul     edi
        or         edx,edx
        jnz        Getvy
        add     ebx,eax  ;累加
        jc        Getvy
        jmp     short GetV10
Getvx:    mov     eax,ebx ;ascii转值后由ax转回
        clc     ;成功cf=0
        jmp     short Getvz
Getvy:    stc      ;错误 cf=1
Getvz:    pop     edi
        pop     ebx
        ret
;-------------------------------------------------------------------
;input    : offset of last string    in si
;output    : value    in hi-lo buffer
htoh:    push     cx
        push     di        
        xor     edx,edx

hh10:    lodsb
        or        al,al
        jz        hh80
        mov     ah,al
        and        ah,05fh     ;转大写
        cmp     ah,'A'    ;排除A-Z
        jb        hh20
        cmp     ah,'Z'
        ja        hh20
        mov     al,ah    ;大写
hh20:    lea        di,hex_table[2]      ;address of ascii_table
        mov        ecx,16          ;no.
        repne    scasb
        jnz        hh90        ;not found 0-F
        sub        di,(offset hex_table[2])+1     ;adjust position
        mov        cx,4
hh30:    shr        di,1          ;shift right side to carry
        rcl        edx,1        ;shift carry to right    side
        jc        hh90        ;overflow
        loop    hh30
        jmp        short hh10

hh80:    mov     eax,edx
        shr     edx,16
        clc
hh88:    pop        di
        pop        cx
        ret
hh90:    stc
        jmp        short hh88
;------------------------------------------------------------------------------
FindNonSpace:    
        mov     di,startpos
        cld
        mov     al,20h
        mov     cx,82
        repe    scasb
        lea     si,[di-1]  ;si=di-1
        mov     cx,82
        mov     edx,0
        ret



[此贴子已经被作者于2016-7-17 07:34编辑过]

2016-07-17 07:26
Valenciax
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:11
帖 子:340
专家分:2482
注 册:2016-5-15
收藏
得分:0 
程序代码:
;------------------------------------------------------------------------------
;2进制转16进制子程序
BtoH:    call    FindNonSpace
        jz        BtoHxx   ;找不到空白之外的字符

BtoH10:    lodsb
        or        al,al    ;zero ?
        jz         BtoH30    
        sub        al,'0'
        cmp     al,1
        ja        BtoHxx
        shr        al,1
        rcl        edx,1
        jc        BtoHxx    ;溢位,离开
        loop    BtoH10
        jmp        short BtoHx ;一直碰不到0,有问题
BtoH30:    mov     eax,edx
        shr        edx,16
        ;dx,ax    ;hex 
BtoHResult:
        mov     word ptr userinput,ax
        mov     word ptr userinput+2,dx
        mov        di,offset OverwriteStr
        mov     ax,word ptr userinput + 2
        or        ax,ax
        jz        BtoH40
        call    Printhex
BtoH40:    mov     ax,word ptr userinput 
        call    Printhex
BtoHx:    clc
        ret
BtoHxx:    stc
        ret
;------------------------------------------------------------------------------
;10进制转16进制子程序
DtoH:    call    FindNonSpace
        jz        DtoHx  ;找不到空白之外的字符
DtoH10:    call    GetValue
        jc        DtoHx
        mov     edx,eax
        shr        edx,16
        jmp        BtoHResult
DtoHx:    stc
        ret
;------------------------------------------------------------------------------
.286
;------------------------------------------------------------------------------
;根据AX值,转换为ASCII
Printhex:
        mov     bx,offset hexTable
        mov     cx,0404h
        mov     dx,ax
printH3:
        mov     ax,dx
        and     ax,000fh
        shr     dx,cl
        xlatb
        push     ax
        dec     ch
        jnz     printH3
        mov     cx,4
printH4:
        pop     ax
        stosb
        loop     printH4
        ret
;------------------------------------------------------------------------------
; dh=row, dl=column
SetCurPos: ;设定光标位置
        push     ax
        push     bx
        mov     ah,2
        mov     bh,0
        int     10h
        pop     bx
        pop     ax
        ret    
;-------------------------------------------------------------------------------
; get char(al) at cursor
GetChAtr:
        push    bx
        mov        bh,0
        mov        ah,08h
        int        10h
        pop        bx
        ret    
;--------------------------------------------------------------------------------
;get cursor posion , dh=row, dl=column
;AH = 03h
;BH = page number
;Return:
;AX = 0000h (Phoenix BIOS)
;CH = start scan line
;CL = end scan line
;DH = row (00h is top)
;DL = column (00h is left)
;读取光标位置
GetCur:    push    ax
        push    bx
        push    cx
        mov        bh,0
        mov        ah,03h
        int        10h
        pop        cx
        pop        bx
        pop        ax
        ret
;--------------------------------------------------------------------------------
;时脉中断,用于定时送出键值,直至送完
NewInt1C:    
        sti
        pushf
        cmp        cs:sendflag,0
        jz        new10        ;没有sendflag设定,走
        cmp        cs:work_flag1,1     ;工作中?
        jz        new10        ;是,走
        mov        cs:work_flag1,1    ;设定工作中
        call    Sendkey    ;送key
        mov        cs:work_flag1,0    ;清除工作中标志
new10:    popf
        pushf
        call    dword ptr cs:old1C_off
        retf    0002h
;--------------------------------------------------------------------------------
;--------------------------以下主程式---------------------------------------
;--------------------------------------------------------------------------------
INIT:    mov        bx,offset sp_end
        mov        sp,bx
        mov        bx,offset end_program
        add        bx,15
        mov        cl,4
        shr        bx,cl
        mov        ah,4ah    ;调整内存,以载入原来debug.exe或
        int        21h    
        mov     bx,1
        call     p_command
        cmp        argc,0
        jz        NoArgv
        mov        dx,argv[0]
        mov        ax,4300h    ;get attrib
        int        21h
        jc        NoArgv
        mov     si,dx
        mov     di,offset userprogram

reRead:    lodsb    
        stosb
        or        al,al
        jnz        reRead

        ;make new psp:80
        cmp        argc,1
        jnz        docopy
        mov        word ptr es:[80h],0d00h
        jmp        short NoArgv
docopy:
        mov     di,82h        ;psp参数起点+2
        mov     cl,es:[di-2]        ;取参数长度
        mov     ch,0        
        mov     bx,cx         
        mov     byte ptr es:[di+bx-1],0dh  ;0dh回车存回
        mov     word ptr [di-2],2000h       ;psp:80
        mov     si,argv[2]
makePsp:lodsb
        stosb
        inc     byte ptr es:[80h]
        cmp     al,0dh
        jnz        makePsp
NoArgv:
        call    set_init    ;设定中断(09h,1ch)

rerun:    mov        si,offset main_file ;载入
        cmp        argc,0
        jz        do_run
        mov        si,offset userprogram    ;user give program name
do_run:    call    do_program ;载入第一个debug(com)
        jnc        allok     ;正常则离开
        cmp        argc,0
        jz        nextproc
        mov     argc,0      ;reset and run my proc again
        mov        word ptr es:[80h],0d00h  ;make psp:80 [no arg]
        jmp     short rerun

nextproc:
        mov        si,offset main_file1 ;载入第2个debug(exe)
        call    do_program
allok:    call    reset_init   ;还原中断(09h,1ch)
quit:    mov    ah,4ch
        int    21h
;------------------------------------------------------------------------------
;设定09,1ch中断
set_init:
        push    es
        mov        ax,3509h
        int        21h
        mov        cs:old09_seg,es
        mov        cs:old09_off,bx
        mov        ax,3516h
        int        21h
        mov        cs:old1C_off,bx
        mov        cs:old1C_seg,es
        mov        ax,2509h
        mov        dx,offset new_int09
        push    cs
        pop        ds
        int        21h
        mov        dx,offset NewInt1C
        mov        ax,2516h
        int        21h
        pop        es
        ret
;------------------------------------------------------------------------------
;还原09,1ch中断
reset_init:        
        push    ds
        mov        ds,cs:old09_seg
        mov        dx,cs:old09_off
        mov        ax,2509h
        int        21h
        mov        ds,cs:old1C_seg
        mov        dx,cs:old1C_off
        mov        ax,2516h
        int        21h
        pop        ds
        ret
;------------------------------------------------------------------------------
;转入程式并运行,ds:si指向的程式名称
do_program      proc    near
;si= offset of program name
        mov        pcb[02h],80h
        mov        pcb[04h],es
        mov        pcb[06h],5ch
        mov        pcb[08h],es
        mov        pcb[0ah],6ch
        mov        pcb[0ch],es
        mov        bx,offset pcb
        cli
        mov        keep_ss,ss
        mov        keep_sp,sp
        sti
        mov        dx,si
        mov        ax,4b00h
        int    21h
        cli
        mov        ss,keep_ss
        mov        sp,keep_sp
        push    cs
        pop        ds
        ret
do_program      endp
;------------------------------------------------------------------------------
;------------------------------------------------------------------------------
;----- Process argument form ds:80h to 100h (command line) --------------------
;bx=Max no. of argument, Set C flag (CY) when argc=0 or argument not enough
p_command:    push ax
        push     cx
        push     dx
        push     bp
        mov     si,81h
        xor     di,di
        xor     cx,cx
        xor     bp,bp
        mov     argc,cl ;clear argument
        mov     cl,es:[si-1] ;get length
        jcxz     pc5 ;no argument ?
        mov     bp,cx
        mov     byte ptr es:[si+bp],0 ; clear 0dh
        mov     ax,0920h ; tab and space
        mov     dx,0001h
pc1:
        cmp     al,es:[si]
        je         pc2
        cmp     ah,es:[si]
        jne     pc3
pc2:
        mov     es:[si],dh
        inc     si
        mov     bp,1
        loop     pc1
        jmp     short pc5
pc3:
        cmp     bp,1
        jne     pc4
        mov     bp,0
        mov     argv[di],si
        inc     di
        inc     di
        inc     argc
pc4:
        inc     si
        loop     pc1
        mov     ds:[si],dh
pc5:
        cmp     argc,dh
        je         pc6
        cmp     argc,bl
        jb         pc6
        clc
        jmp     short pc7
pc6:
        stc
pc7:
        pop     bp
        pop     dx
        pop     cx
        pop     ax
        ret
;------------------------------------------------------------------------------
sp_end        equ    $  +  200
end_program    equ    $  +  201

cseg    ends
END       begin                   ; end program


[此贴子已经被作者于2016-7-17 07:30编辑过]

2016-07-17 07:26
zhulei1978
Rank: 20Rank: 20Rank: 20Rank: 20Rank: 20
等 级:版主
威 望:53
帖 子:1351
专家分:1200
注 册:2006-12-17
收藏
得分:0 
好长的代码

其实我就是改变社会风气,提高少女素质,刺激电影市道,提高年轻人内涵,玉树临风,风度翩翩的整蛊专家,我名叫古晶,英文名叫JingKoo!
2016-07-17 08:32
快速回复:大家来玩玩这道题!
数据加载中...
 
   



关于我们 | 广告合作 | 编程中国 | 清除Cookies | TOP | 手机版

编程中国 版权所有,并保留所有权利。
Powered by Discuz, Processed in 0.056655 second(s), 9 queries.
Copyright©2004-2024, BCCN.NET, All Rights Reserved