📄 memedit.asm
字号:
quit: mov a, r6 anl a, #11110000b swap a cpl a add a, #19 acall cursor_down ajmp newlineascii_only: anl a, #01111111b ;avoid unprintable characters cjne a, #127, aonly2 mov a, #' ' retaonly2: clr c subb a, #32 jnc aonly3 ;avoid control characters mov a, #(' ' - 32)aonly3: add a, #32 retread_dptr: mov a, r4 jb acc.0, rddptr2 clr a movc a, @a+dptr retrddptr2:movx a, @dptr retread_r6r7: push dph push dpl mov dph, r7 mov dpl, r6 mov a, r4 jb acc.3, rdr6r7d jb acc.0, rdr6r7b clr a movc a, @a+dptr sjmp rdr6r7crdr6r7b:movx a, @dptrrdr6r7c:pop dpl pop dph retrdr6r7d:mov a, r5 sjmp rdr6r7c.equ esc_char, 27cursor_home: acall term_esc mov a, #'H' ajmp coutcursor_down: ;acc is # of lines to move down acall term_esc acall pint mov a, #'B' ajmp coutcursor_up: ;acc is # of lines to move up acall term_esc acall pint mov a, #'A' ajmp coutcursor_left: ;acc is # of characters to move left acall term_esc acall pint mov a, #'D' ajmp coutcursor_right: ;acc is # of characters to move right acall term_esc acall pint mov a, #'C' ajmp coutinverse_on: mov dptr, #str_so ajmp pstrstr_so: .db esc_char, "[0;7m", 0inverse_off: mov dptr, #str_se ajmp pstrstr_se: .db esc_char, "[0m", 0term_esc: push acc mov a, #esc_char acall cout mov a, #'[' acall cout pop acc ret print_addr_line: mov dptr, #str_addr acall pstr mov r0, #0paddrl: acall space mov a, #'+' acall cout mov a, r0 acall phex1 inc r0 cjne r0, #16, paddrl mov dptr, #str_ascii_equiv ajmp pstrprint_dash_line: mov r0, #72pdashl: mov a, #'-' acall cout djnz r0, pdashl retprint_title_line: mov a, r4 jb acc.0, ptitle2 mov dptr, #str_code sjmp ptitle3ptitle2:mov dptr, #str_dataptitle3:acall pstr mov r0, #8ptitlel:acall space djnz r0, ptitlel mov dptr, #str_title ajmp pstrerase_commands: acall cursor_home mov a, #20 acall cursor_down mov r2, #72ercmd2: acall space djnz r2, ercmd2 mov a, #72 ajmp cursor_left; R4, Flags:; bit0: 0=display CODE memory, 1=display DATA memory; bit1: 0=editing disabled, 1=editing enabled; bit2: 0=editing in hex, 1=editing in ascii; bit3: 0=normal, 1=in middle of hex entry (value in r5)print_commands: mov a, r4 jnb acc.1, pcmd_no_edit mov dptr, #str_cmd3 jb acc.2, pcmd_ascii mov dptr, #str_cmd4pcmd_ascii: acall pstr mov dptr, #str_cmd5 acall pstr sjmp pcmd_finishpcmd_no_edit: mov dptr, #str_cmd2 acall pstrpcmd_finish: mov dptr, #str_cmd1 ajmp pstrstr_cmd1: .db " ^G=Goto ^C=Code ^D=Data ^L=Redraw ^Q=Quit", 0str_cmd2: .db "^E-Edit",0str_cmd3: .db "^A=", esc_char, "[0;7m", "ASCII", esc_char, "[0m", " ^X=Hex", 0str_cmd4: .db "^A=ASCII ^X=", esc_char, "[0;7m", "Hex", esc_char, "[0m", 0str_cmd5: .db " ^F=Fill",0str_cl: .db esc_char, "[H", esc_char, "[2J", 0str_addr: .db "ADDR:",0str_ascii_equiv: .db " ASCII EQUIVILANT",0str_title: .db "8051 External Memory Editor, Paul Stoffregen, 1996",0str_code: .db "CODE",0str_data: .db "DATA",0;this twisted bit of code looks for escape sequences for;up, down, left, right, pageup, and pagedown, as well;as ordinary escape and ordinary characters. Escape;sequences are required to arrive with each character;nearly back-to-back to the others, otherwise the characters;are treated as ordinary user keystroaks. cin_filter;returns a single byte when it sees the multi-byte escape;sequence, as shown here.; return value key escape sequence; 11 (^K) up 1B 5B 41; 10 (^J) down 1B 5B 42; 21 (^U) right 1B 5B 43; 8 (^H) left 1B 5B 44; 25 (^Y) page up 1B 5B 35 7E; 26 (^Z) page down 1B 5B 36 7Ecin_filter: jnb ri, cinf1 acall cin cjne a, #esc_char, cinf_end ;if esc was already in sbuf, just ignore itcinf1: acall cin cjne a, #esc_char, cinf_endcinf2: acall cinf_wait jb ri, cinf4 mov a, #esc_char ret ;an ordinary ESCcinf4: ;if we get here, it's a control code, since a character ;was received shortly after receiving an ESC character acall cin cjne a, #'[', cinf_consume acall cinf_wait jnb ri, cin_filter acall cincinf5a: cjne a, #'A', cinf5b mov a, #11 retcinf5b: cjne a, #'B', cinf5c mov a, #10 retcinf5c: cjne a, #'C', cinf5d mov a, #21 retcinf5d: cjne a, #'D', cinf5e mov a, #8 retcinf5e: cjne a, #0x35, cinf5f sjmp cinf8cinf5f: cjne a, #0x36, cinf5g sjmp cinf8cinf5g: sjmp cinf_consume ;unknown escape sequencecinf8: ;when we get here, we've got the sequence for pageup/pagedown ;but there's one more incoming byte to check... push acc acall cinf_wait jnb ri, cinf_restart acall cin cjne a, #0x7E, cinf_notpg pop acc add a, #228cinf_end: retcinf_restart: pop acc sjmp cin_filtercinf_notpg: pop acc;unrecognized escape... eat up everything that's left coming in;quickly, then begin looking againcinf_consume: acall cinf_wait jnb ri, cin_filter acall cin cjne a, #esc_char, cinf_consume sjmp cinf2;this thing waits for a character to be received for approx;4 character transmit time periods. It returns immedately;or after the entire wait time. It does not remove the character;from the buffer, so ri should be checked to see if something;actually did show up while it was waiting .equ char_delay, 4 ;number of char xmit times to waitcinf_wait: mov a, r2 push acc mov r2, #char_delay*5cinfw2: mov a, th0cinfw3: jb ri, cinfw4 inc a jnz cinfw3 djnz r2, cinfw2cinfw4: pop acc mov r2, a ret;converts the ascii code in Acc to uppercase, if it is lowercase; Code efficient (saves 6 byes) upper contributed; by Alexander B. Alexandrov <abalex@cbr.spb.ru>upper: cjne a, #97, upper2upper2: jc upper4 ;end if acc < 97 cjne a, #123, upper3upper3: jnc upper4 ;end if acc >= 123 add a, #224 ;convert to uppercaseupper4: ret ;carry set if esc pressed ;psw.5 set if return pressed w/ no inputghex16: mov r2, #0 ;start out with 0 mov r3, #0 mov r4, #4 ;number of digits left clr psw.5ghex16c: acall cin_filter acall upper cjne a, #27, ghex16d setb c ;handle esc key clr a mov dph, a mov dpl, a retghex16d:cjne a, #8, ghex16f sjmp ghex16kghex16f:cjne a, #127, ghex16g ;handle backspaceghex16k:cjne r4, #4, ghex16e ;have they entered anything yet? sjmp ghex16cghex16e:acall cout acall ghex16y inc r4 sjmp ghex16cghex16g:cjne a, #13, ghex16i ;return key mov dph, r3 mov dpl, r2 cjne r4, #4, ghex16h clr a mov dph, a mov dpl, a setb psw.5ghex16h:clr c retghex16i:mov r5, a ;keep copy of original keystroke acall asc2hex jc ghex16c xch a, r5 lcall cout mov a, r5 push acc acall ghex16x pop acc add a, r2 mov r2, a clr a addc a, r3 mov r3, a djnz r4, ghex16c clr c mov dpl, r2 mov dph, r3 retghex16x: ;multiply r3-r2 by 16 (shift left by 4) mov a, r3 swap a anl a, #11110000b mov r3, a mov a, r2 swap a anl a, #00001111b orl a, r3 mov r3, a mov a, r2 swap a anl a, #11110000b mov r2, a retghex16y: ;divide r3-r2 by 16 (shift right by 4) mov a, r2 swap a anl a, #00001111b mov r2, a mov a, r3 swap a anl a, #11110000b orl a, r2 mov r2, a mov a, r3 swap a anl a, #00001111b mov r3, a ret ;carry set if invalid inputasc2hex: add a, #208 jnc hex_not add a, #246 jc hex_maybe add a, #10 clr c rethex_maybe: add a, #249 jnc hex_not add a, #250 jc hex_not add a, #16 clr c rethex_not:setb c ret ;get 2 digit hex number from serial port ; c = set if ESC pressed, clear otherwise ; psw.5 = set if return w/ no input, clear otherwiseghex:ghex8: clr psw.5ghex8c: acall cin_filter ;get first digit acall upper cjne a, #27, ghex8fghex8d: setb c clr a retghex8f: cjne a, #13, ghex8h setb psw.5 clr c clr a retghex8h: mov r2, a acall asc2hex jc ghex8c xch a, r2 ;r2 will hold hex value of 1st digit acall coutghex8j: acall cin_filter ;get second digit acall upper cjne a, #27, ghex8k sjmp ghex8dghex8k: cjne a, #13, ghex8m mov a, r2 clr c retghex8m: cjne a, #8, ghex8pghex8n: acall cout sjmp ghex8cghex8p: cjne a, #21, ghex8q sjmp ghex8nghex8q: mov r3, a acall asc2hex jc ghex8j xch a, r3 acall cout mov a, r2 swap a orl a, r3 clr c retcin: jnb ri, cin clr ri mov a, sbuf retspace: mov a, #' 'cout: jnb ti, cout clr ti ;clr ti before the mov to sbuf! mov sbuf, a retphex16: push acc mov a, dph acall phex mov a, dpl acall phex pop acc ret; Highly code efficient resursive call phex contributed; by Alexander B. Alexandrov <abalex@cbr.spb.ru>phex:phex8: acall phex_bphex_b: swap a ;SWAP A will be twice => A unchangedphex1: push acc anl a, #15 add a, #0x90 ; acc is 0x9X, where X is hex digit da a ; if A to F, C=1 and lower four bits are 0..5 addc a, #0x40 da a acall cout pop acc ret;a not so well documented feature of pstr is that you can print;multiple consecutive strings without needing to reload dptr;(which takes 3 bytes of code!)... this is useful for inserting;numbers or spaces between strings.pstr: push accpstr1: clr a movc a, @a+dptr inc dptr jz pstr2 mov c, acc.7 anl a, #0x7F acall cout jc pstr2 sjmp pstr1pstr2: pop acc retnewline:push acc ;print one newline mov a, #13 acall cout mov a, #10 acall cout pop acc retpint8u: ;prints the unsigned 8 bit value in Acc in base 10 push b push acc sjmp pint8bpint:pint8: ;prints the signed 8 bit value in Acc in base 10 push b push acc jnb acc.7, pint8b mov a, #'-' lcall cout pop acc push acc cpl a add a, #1pint8b: mov b, #100 div ab setb f0 jz pint8c clr f0 add a, #'0' lcall coutpint8c: mov a, b mov b, #10 div ab jnb f0, pint8d jz pint8epint8d: add a, #'0' lcall coutpint8e: mov a, b add a, #'0' lcall cout pop acc pop b ret
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -