Become a fan of Slashdot on Facebook

 



Forgot your password?
typodupeerror
×
User Journal

Journal Journal: MD5 in 80x86 (MASM)

You'll have to assemble this one with MASM. I don't feel like adapting it for debug...

How to assemble: Copy and paste into notepad, save as md5.asm, and assemble with MASM to create md5.exe.

; +-- MD5 -- d9dfaaaf50701ed5851a58123cbaf925284218aee788f4cc3c11e1d7d2f96721 -->
; | --> started 22.aug.08 -- completed 24.aug.08 <--
; | The MD5 function implemented in 80x86 assembly language
; | Calculates the hash of an input string MSG of length LEN.
; | The MD5 procedure stores the hash as a 16-byte binary value beginning at H0.
; | The PRINT procedure displays the 16-bit binary hash as 32-digit hexadecimal.
; +----------------------------------------------------------------------------->
 
; This is the maximum string length.
; It has to be 0-255 because INT 10h can't input longer strings than 255 bytes.
; If you're using the MD5 proc to hash longer data, you'll have to input it somehow
; and store the data length in LEN, which is a word (allowing an input data size
; up to 64k, if you change the .MODEL directive).
MAX_LEN EQU 255
 
; -- Macro definitions -----------------------------
FnF MACRO i
            MOV AX, VC ; f = d xor (b and (c xor d))
            MOV BX, VC+2
            XOR AX, VD
            XOR BX, VD+2
            AND AX, VB
            AND BX, VB+2
            XOR AX, VD
            XOR BX, VD+2
            MOV VF, AX
            MOV VF+2, BX
 
            MOV BYTE PTR VG, i ; g = i
            ENDM
 
FnG MACRO i
            MOV AX, VB ; f = c xor (d and (b xor c))
            MOV BX, VB+2
            XOR AX, VC
            XOR BX, VC+2
            AND AX, VD
            AND BX, VD+2
            XOR AX, VC
            XOR BX, VC+2
            MOV VF, AX
            MOV VF+2, BX
 
            MOV CL, i ; g = (5*i + 1) mod 16
            SHL CL, 1
            SHL CL, 1
            ADD CL, i
            INC CL
            AND CL, 0Fh
            MOV VG, CL
            ENDM
 
FnH MACRO i
            MOV AX, VB ; f = b xor c xor d
            MOV BX, VB+2
            XOR AX, VC
            XOR BX, VC+2
            XOR AX, VD
            XOR BX, VD+2
            MOV VF, AX
            MOV VF+2, BX
 
            MOV CL, i ; g = (3*i + 5) mod 16
            SHL CL, 1
            ADD CL, i
            ADD CL, 5
            AND CL, 0Fh
            MOV VG, CL
            ENDM
 
FnI MACRO i
            MOV AX, VD ; f = c xor (b or (not d))
            MOV BX, VD+2
            NOT AX
            NOT BX
            OR AX, VB
            OR BX, VB+2
            XOR AX, VC
            XOR BX, VC+2
            MOV VF, AX
            MOV VF+2, BX
 
            MOV CX, i ; g = (7*i) mod 16
            SHL CX, 1 ; 16-bit. 63*8 doesn't fit in 8 bits.
            SHL CX, 1
            SHL CX, 1
            SUB CX, i
            AND CL, 0Fh
            MOV VG, CL
            ENDM
 
UpdVars MACRO Rn, Kn_L, Kn_H
            LOCAL LOOP
 
            MOV AX, VD ; temp = d
            MOV TEMP, AX
            MOV AX, VD+2
            MOV TEMP+2, AX
 
            MOV AX, VC ; d = c
            MOV VD, AX
            MOV AX, VC+2
            MOV VD+2, AX
 
            MOV AX, VB ; c = b
            MOV VC, AX
            MOV AX, VB+2
            MOV VC+2, AX
 
            MOV AX, VA ; BX:AX = (a + f + Kn + w[g])
            MOV BX, VA+2
            MOV CX, VF
            ADD AX, CX
            MOV CX, VF+2
            ADC BX, CX ; Add with carry
            ADD AX, Kn_L
            ADC BX, Kn_H
            MOV SI, DI ; SI points to the beginning of this chunk
            XOR CH, CH ; Clear CH
            MOV CL, VG
            SHL CX, 1
            SHL CX, 1 ; Multiply VG*4 to find the offset of w[g]
            ADD SI, CX ; SI points to w[g]
            MOV CX, [SI]
            ADD AX, CX
            MOV CX, [SI]+2
            ADC BX, CX
            ; Now rotate BX:AX to the left Rn times
            MOV CL, Rn
LOOP: SHL AX, 1 ; Bit shifted out of low word goes into carry
            RCL BX, 1 ; Shift left & shift carry into LSB of high word
            ADC AL, 0 ; Bring carry bit back into LSB of low byte
            DEC CL
            JNZ LOOP ; Loop Rn times
 
            ADD VB, AX ; VB = VB + BX:AX
            ADC VB+2, BX
 
            MOV AX, TEMP ; a = temp
            MOV VA, AX
            MOV AX, TEMP+2
            MOV VA+2, AX
            ENDM
 
; Compares two 16-byte values. I'm not using this but it might be useful in the future.
; DS:SI = address of first value, ES:DI = address of 2nd value.
; Return: ZR if equal, NZ if unequal
Comp MACRO
            MOV CX, 16
            REPE CMPSB
            ENDM
; -- End macro definitions -------------------------
 
.MODEL SMALL
.STACK 64
 
.DATA
; MAX_L, ACTUAL, and MSG must be adjacent in this order. Don't mess with them.
MAX_L DB MAX_LEN ; Don't change this, change the MAX_LEN EQU instead.
ACTUAL DB ? ; This is where DOS will put the actual string length
MSG DB MAX_LEN DUP (?) ; Holds the string that we'll be hashing
            DB 8 DUP (?), 64 DUP (?) ; Space to pad the message. Don't change this either.
LEN DW ? ; ACTUAL gets copied here. MD5 uses this, not ACTUAL.
PROMPT DB "Enter string: $"
 
; These 4 dwords will hold the MD5 hash as it's being calculated and the final result
H0 DW ?,?
H1 DW ?,?
H2 DW ?,?
H3 DW ?,?
; These will hold intermediate values
VA DW ?,?
VB DW ?,?
VC DW ?,?
VD DW ?,?
VF DW ?,?
VG DB ?
TEMP DW ?,?
 
; Un-comment the appropriate line to give upper/lowercase hex when printing an MD5 hash.
HEX DB "0123456789abcdef"
;HEX DB "0123456789ABCDEF"
 
; Initial values for H0-H3 and VA-VD.
; Loaded in 16-bit words because we can't address a dword.
H0_H EQU 6745h
H0_L EQU 2301h
H1_H EQU 0EFCDh
H1_L EQU 0AB89h
H2_H EQU 98BAh
H2_L EQU 0DCFEh
H3_H EQU 1032h
H3_L EQU 5476h
 
; Array of K dword values: k[i] = floor(abs(sin(i + 1)) * (2^32))
K0_H EQU 0D76Ah
K0_L EQU 0A478h
K1_H EQU 0E8C7h
K1_L EQU 0B756h
K2_H EQU 2420h
K2_L EQU 70DBh
K3_H EQU 0C1BDh
K3_L EQU 0CEEEh
K4_H EQU 0F57Ch
K4_L EQU 0FAFh
K5_H EQU 4787h
K5_L EQU 0C62Ah
K6_H EQU 0A830h
K6_L EQU 4613h
K7_H EQU 0FD46h
K7_L EQU 9501h
K8_H EQU 6980h
K8_L EQU 98D8h
K9_H EQU 8B44h
K9_L EQU 0F7AFh
K10_H EQU 0FFFFh
K10_L EQU 5BB1h
K11_H EQU 895Ch
K11_L EQU 0D7BEh
K12_H EQU 6B90h
K12_L EQU 1122h
K13_H EQU 0FD98h
K13_L EQU 7193h
K14_H EQU 0A679h
K14_L EQU 438Eh
K15_H EQU 49B4h
K15_L EQU 0821h
K16_H EQU 0F61Eh
K16_L EQU 2562h
K17_H EQU 0C040h
K17_L EQU 0B340h
K18_H EQU 265Eh
K18_L EQU 5A51h
K19_H EQU 0E9B6h
K19_L EQU 0C7AAh
K20_H EQU 0D62Fh
K20_L EQU 105Dh
K21_H EQU 0244h
K21_L EQU 1453h
K22_H EQU 0D8A1h
K22_L EQU 0E681h
K23_H EQU 0E7D3h
K23_L EQU 0FBC8h
K24_H EQU 21E1h
K24_L EQU 0CDE6h
K25_H EQU 0C337h
K25_L EQU 07D6h
K26_H EQU 0F4D5h
K26_L EQU 0D87h
K27_H EQU 455Ah
K27_L EQU 14EDh
K28_H EQU 0A9E3h
K28_L EQU 0E905h
K29_H EQU 0FCEFh
K29_L EQU 0A3F8h
K30_H EQU 676Fh
K30_L EQU 02D9h
K31_H EQU 8D2Ah
K31_L EQU 4C8Ah
K32_H EQU 0FFFAh
K32_L EQU 3942h
K33_H EQU 8771h
K33_L EQU 0F681h
K34_H EQU 6D9Dh
K34_L EQU 6122h
K35_H EQU 0FDE5h
K35_L EQU 380Ch
K36_H EQU 0A4BEh
K36_L EQU 0EA44h
K37_H EQU 4BDEh
K37_L EQU 0CFA9h
K38_H EQU 0F6BBh
K38_L EQU 4B60h
K39_H EQU 0BEBFh
K39_L EQU 0BC70h
K40_H EQU 289Bh
K40_L EQU 7EC6h
K41_H EQU 0EAA1h
K41_L EQU 27FAh
K42_H EQU 0D4EFh
K42_L EQU 3085h
K43_H EQU 0488h
K43_L EQU 1D05h
K44_H EQU 0D9D4h
K44_L EQU 0D039h
K45_H EQU 0E6DBh
K45_L EQU 99E5h
K46_H EQU 1FA2h
K46_L EQU 7CF8h
K47_H EQU 0C4ACh
K47_L EQU 5665h
K48_H EQU 0F429h
K48_L EQU 2244h
K49_H EQU 432Ah
K49_L EQU 0FF97h
K50_H EQU 0AB94h
K50_L EQU 23A7h
K51_H EQU 0FC93h
K51_L EQU 0A039h
K52_H EQU 655Bh
K52_L EQU 59C3h
K53_H EQU 8F0Ch
K53_L EQU 0CC92h
K54_H EQU 0FFEFh
K54_L EQU 0F47Dh
K55_H EQU 8584h
K55_L EQU 5DD1h
K56_H EQU 6FA8h
K56_L EQU 7E4Fh
K57_H EQU 0FE2Ch
K57_L EQU 0E6E0h
K58_H EQU 0A301h
K58_L EQU 4314h
K59_H EQU 4E08h
K59_L EQU 11A1h
K60_H EQU 0F753h
K60_L EQU 7E82h
K61_H EQU 0BD3Ah
K61_L EQU 0F235h
K62_H EQU 2AD7h
K62_L EQU 0D2BBh
K63_H EQU 0EB86h
K63_L EQU 0D391h
 
; Per-round shift amounts.
; Every 4 values repeat to fill gaps, i.e. 4-15 are 7,12,17,22,7,12,17,22,7,12,17,22.
R0 EQU 7
R1 EQU 12
R2 EQU 17
R3 EQU 22
R16 EQU 5
R17 EQU 9
R18 EQU 14
R19 EQU 20
R32 EQU 4
R33 EQU 11
R34 EQU 16
R35 EQU 23
R48 EQU 6
R49 EQU 10
R50 EQU 15
R51 EQU 21
 
.CODE
MAIN PROC FAR
            ; Set up the segment registers
            MOV AX, @DATA
            MOV DS, AX
            MOV ES, AX
 
            ; Code
            MOV AH, 09h
            MOV DX, OFFSET PROMPT
            INT 21h ; Display a prompt
 
            MOV AH, 0Ah
            MOV DX, OFFSET MAX_L
            INT 21h ; Get user-entered string to hash
 
            MOV AH, 03h
            MOV BH, 0
            INT 10h ; Get the cursor position
            MOV AH, 02h
            MOV DL, 79
            INT 10h ; Move the cursor to column 80
            MOV AH, 02h
            MOV DL, " "
            INT 21h ; Print a space to move to the next row
 
            XOR AH, AH
            MOV AL, ACTUAL
            MOV LEN, AX ; Store length in LEN as 16-bit
 
            MOV AX, OFFSET MSG
            MOV BX, LEN
            PUSH AX ; Push the arguments onto the stack
            PUSH BX
            CALL MD5 ; Calculate the MD5 of the string
            ADD SP, 4 ; Clear the arguments from the stack
 
            MOV AX, OFFSET H0 ; Get a pointer to the MD5 hash
            PUSH AX
            CALL PRINT ; Print the result
            ADD SP, 2
 
            ; Return to DOS
DONE: MOV AH, 4Ch
            INT 21h
MAIN ENDP
 
; -- Procedures ---------------------------------------------------------------
 
; Calculates the MD5 hash of a string.
; Pass a 16-bit pointer to the string and the string length as a 16-bit number.
; Arguments must be passed by pushing them onto the stack in that order.
MD5 PROC
            PUSH AX
            PUSH BX
            PUSH CX
            PUSH DX
            PUSH BP
            MOV BP, SP
 
            ; Arguments:
            ; [BP]+12: string length (16-bit)
            ; [BP]+14: pointer to string (16-bit)
 
            ; Initialize variables:
            ; copy H0_H:H0_L to H0
            MOV DI, OFFSET H0
            MOV AX, H0_L
            MOV BX, H0_H
            MOV [DI], AX
            MOV [DI]+2, BX
            ; copy H1_H:H1_L to H1
            MOV DI, OFFSET H1
            MOV AX, H1_L
            MOV BX, H1_H
            MOV [DI], AX
            MOV [DI]+2, BX
            ; copy H2_H:H2_L to H2
            MOV DI, OFFSET H2
            MOV AX, H2_L
            MOV BX, H2_H
            MOV [DI], AX
            MOV [DI]+2, BX
            ; copy H3_H:H3_L to H3
            MOV DI, OFFSET H3
            MOV AX, H3_L
            MOV BX, H3_H
            MOV [DI], AX
            MOV [DI]+2, BX
 
            ; Pre-processing:
            MOV DI, [BP]+14 ; DI points to the string to hash
            MOV BX, [BP]+12 ; BX holds the length of the string
            AND BX, 0FFC0h ; BX = INT(BX/64)*64
            ADD DI, BX ; DI points to the last 64-byte chunk
            MOV BX, [BP]+12
            AND BX, 003Fh ; BX = length MOD 64, last chunk length
            MOV BYTE PTR [BX+DI], 80h ; Pad with binary 10000000
 
PP0: INC BX ; Increment chunk length
            AND BX, 003Fh ; MOD 64 again
            JNZ PP1
            ADD DI, 0040h ; Add 64 to the chunk pointer
PP1: CMP BX, 0038h ; Stop if we've reached the 57th byte
            JZ PP2
            MOV BYTE PTR [BX+DI], 00h ; Pad with more 0's
            JMP PP0 ; Loop until chunk is 56 bytes long
 
PP2: MOV AX, [BP]+12 ; AX holds the un-padded string length
            MOV CX, 8 ; bits per byte
            MUL CX ; DX:AX = original string length in bits
            MOV [BX+DI], AX ; Append length (64-bit little endian)
            MOV [BX+DI]+2, DX
            MOV WORD PTR [BX+DI]+4, 0000h
            MOV WORD PTR [BX+DI]+6, 0000h
            ADD BX, 8 ; Increase the string length
            ADD BX, DI
            MOV DI, [BP]+14 ; Point to the beginning of the string
            SUB BX, DI
            MOV DX, BX ; DX = total string length (in bytes)
 
CHUNK: ; Initialize hash value for this chunk:
            MOV AX, H0 ; Set VA = H0
            MOV VA, AX
            MOV AX, H0+2
            MOV VA+2, AX
 
            MOV AX, H1 ; Set VB = H1
            MOV VB, AX
            MOV AX, H1+2
            MOV VB+2, AX
 
            MOV AX, H2 ; Set VC = H2
            MOV VC, AX
            MOV AX, H2+2
            MOV VC+2, AX
 
            MOV AX, H3 ; Set VD = H3
            MOV VD, AX
            MOV AX, H3+2
            MOV VD+2, AX
 
; ~~ Loops 0-15/63 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            FnF 0 ; f = d xor (b and (c xor d)), g = i
            UpdVars R0, K0_L, K0_H
 
            FnF 1
            UpdVars R1, K1_L, K1_H
 
            FnF 2
            UpdVars R2, K2_L, K2_H
 
            FnF 3
            UpdVars R3, K3_L, K3_H
 
            FnF 4
            UpdVars R0, K4_L, K4_H
 
            FnF 5
            UpdVars R1, K5_L, K5_H
 
            FnF 6
            UpdVars R2, K6_L, K6_H
 
            FnF 7
            UpdVars R3, K7_L, K7_H
 
            FnF 8
            UpdVars R0, K8_L, K8_H
 
            FnF 9
            UpdVars R1, K9_L, K9_H
 
            FnF 10
            UpdVars R2, K10_L, K10_H
 
            FnF 11
            UpdVars R3, K11_L, K11_H
 
            FnF 12
            UpdVars R0, K12_L, K12_H
 
            FnF 13
            UpdVars R1, K13_L, K13_H
 
            FnF 14
            UpdVars R2, K14_L, K14_H
 
            FnF 15
            UpdVars R3, K15_L, K15_H
 
; ~~ Loops 16-31/63 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            FnG 16
            UpdVars R16, K16_L, K16_H
 
            FnG 17
            UpdVars R17, K17_L, K17_H
 
            FnG 18
            UpdVars R18, K18_L, K18_H
 
            FnG 19
            UpdVars R19, K19_L, K19_H
 
            FnG 20
            UpdVars R16, K20_L, K20_H
 
            FnG 21
            UpdVars R17, K21_L, K21_H
 
            FnG 22
            UpdVars R18, K22_L, K22_H
 
            FnG 23
            UpdVars R19, K23_L, K23_H
 
            FnG 24
            UpdVars R16, K24_L, K24_H
 
            FnG 25
            UpdVars R17, K25_L, K25_H
 
            FnG 26
            UpdVars R18, K26_L, K26_H
 
            FnG 27
            UpdVars R19, K27_L, K27_H
 
            FnG 28
            UpdVars R16, K28_L, K28_H
 
            FnG 29
            UpdVars R17, K29_L, K29_H
 
            FnG 30
            UpdVars R18, K30_L, K30_H
 
            FnG 31
            UpdVars R19, K31_L, K31_H
 
; ~~ Loops 32-47/63 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            FnH 32
            UpdVars R32, K32_L, K32_H
 
            FnH 33
            UpdVars R33, K33_L, K33_H
 
            FnH 34
            UpdVars R34, K34_L, K34_H
 
            FnH 35
            UpdVars R35, K35_L, K35_H
 
            FnH 36
            UpdVars R32, K36_L, K36_H
 
            FnH 37
            UpdVars R33, K37_L, K37_H
 
            FnH 38
            UpdVars R34, K38_L, K38_H
 
            FnH 39
            UpdVars R35, K39_L, K39_H
 
            FnH 40
            UpdVars R32, K40_L, K40_H
 
            FnH 41
            UpdVars R33, K41_L, K41_H
 
            FnH 42
            UpdVars R34, K42_L, K42_H
 
            FnH 43
            UpdVars R35, K43_L, K43_H
 
            FnH 44
            UpdVars R32, K44_L, K44_H
 
            FnH 45
            UpdVars R33, K45_L, K45_H
 
            FnH 46
            UpdVars R34, K46_L, K46_H
 
            FnH 47
            UpdVars R35, K47_L, K47_H
 
; ~~ Loops 48-63/63 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
            FnI 48
            UpdVars R48, K48_L, K48_H
 
            FnI 49
            UpdVars R49, K49_L, K49_H
 
            FnI 50
            UpdVars R50, K50_L, K50_H
 
            FnI 51
            UpdVars R51, K51_L, K51_H
 
            FnI 52
            UpdVars R48, K52_L, K52_H
 
            FnI 53
            UpdVars R49, K53_L, K53_H
 
            FnI 54
            UpdVars R50, K54_L, K54_H
 
            FnI 55
            UpdVars R51, K55_L, K55_H
 
            FnI 56
            UpdVars R48, K56_L, K56_H
 
            FnI 57
            UpdVars R49, K57_L, K57_H
 
            FnI 58
            UpdVars R50, K58_L, K58_H
 
            FnI 59
            UpdVars R51, K59_L, K59_H
 
            FnI 60
            UpdVars R48, K60_L, K60_H
 
            FnI 61
            UpdVars R49, K61_L, K61_H
 
            FnI 62
            UpdVars R50, K62_L, K62_H
 
            FnI 63
            UpdVars R51, K63_L, K63_H
 
            ; Add the hash values for this 64-byte chunk
            MOV AX, VA ; h0 = h0 + a
            ADD H0, AX
            MOV AX, VA+2
            ADC H0+2, AX
            MOV AX, VB ; h1 = h1 + b
            ADD H1, AX
            MOV AX, VB+2
            ADC H1+2, AX
            MOV AX, VC ; h2 = h2 + c
            ADD H2, AX
            MOV AX, VC+2
            ADC H2+2, AX
            MOV AX, VD ; h3 = h3 + d
            ADD H3, AX
            MOV AX, VD+2
            ADC H3+2, AX
 
            ADD DI, 64 ; Increase the chunk pointer
            SUB DX, 64 ; Decrease the string length
            JNZ CHUNK ; Hash the next chunk if not done
 
            POP BP
            POP DX
            POP CX
            POP BX
            POP AX
            RET
MD5 ENDP
 
PRINT PROC
            PUSH AX
            PUSH BX
            PUSH CX
            PUSH DX
            PUSH BP
            MOV BP, SP
 
            ; Arguments:
            ; [BP]+12: pointer to the 16-byte binary hash
 
            MOV AH, 2 ; Set AH for INT 21h (output character)
            XOR BH, BH ; This should always = 0
 
            MOV SI, OFFSET HEX
            MOV DI, [BP]+12 ; DI points to the first byte
            MOV CL, 16 ; Set up the loop counter
 
PRN_BYTE: MOV BL, [DI] ; Get the next byte
            SHR BL, 1 ; Get high nibble by shifting right 4x
            SHR BL, 1
            SHR BL, 1
            SHR BL, 1
            MOV DL, [SI+BX] ; Get the ASCII hex digit
            INT 21h ; Print it
 
            MOV BL, [DI] ; Get the current byte again
            AND BL, 0Fh ; Get the low nibble
            MOV DL, [SI+BX] ; Get the hex digit
            INT 21h ; And print it
 
            INC DI ; Point to the next byte
            DEC CL
            JNZ PRN_BYTE ; Loop back until we're done
 
            POP BP
            POP DX
            POP CX
            POP BX
            POP AX
            RET
PRINT ENDP
            END MAIN

User Journal

Journal Journal: HTML/80x86 polyglot

Don't even ask...

javascript:void(prompt("Source code",unescape("<!-- %u0152\xC8%u017D\xD8\xBAP!\x81\xF2%20%20\xB4)%u20AC\xF4 \xCD!\xB4L0\xC0\xCD! --><html><head></head><body><script type=\x22text/javascript\x22>document.write(String(\x22Hello world!$\x22).split(\x22$\x22)[0])\x3B</script></body></html>")));

Copy and paste into the address bar (IE or FF tested). Copy the prompted value and paste it into Notepad; that's the source code*. Save as polyglot.[com|htm] (ANSI encoding) and run. Note: the 80x86 implementation doesn't wait around, so run it from the command prompt or the window will disappear before you see the output.

*Because /. doesn't like the strange characters, I can't post the source code directly. However, once you've saved it as .htm in Notepad as described above – Unicode weirdness notwithstanding – opening it with a browser, viewing the source, copying and pasting into Notepad, and saving as .com should yield an identical copy of the program.

Note: The String() value is the actual data that the 80x86 code displays. As a result, you can easily change it to whatever pleases you. (Leave the $ at the end; it's the delimiter for the interrupt that prints the string. Consequentially, you can't print a string containing a $ character.) However, the beginning of the string is hard-coded, so you won't be able to change the HTML before it (for example to add a <title> value)... actually, try it and see what happens (don't make the HTML shorter though...).

User Journal

Journal Journal: Binary-to-ASCII (80x86)

Binary-to-ASCII in 80x86 assembly (oblig: ASCII-to-binary)

@echo off
goto batch
 
a
        mov ax,cs
        mov ds,ax
        xor bh,bh ;page number (always 0)
;_begin
        xor cx,cx ;initialize bit count (ch) and ascii char (cl)
        mov ah,08
        int 10 ;get the character under the cursor
        mov bl,al ;save it so we can restore it later
;_getch
        mov ah,08
        int 21 ;get a key
        cmp al,1b ;check for esc
        jz 014d ;goto _quit
        cmp al,1a ;check for ^z
        jz 014d ;goto _quit
        cmp al,30 ;check for "0"
        jz 0124 ;goto _procch
        cmp al,31 ;check for "1"
        jz 0124 ;goto _procch
        jmp 010e ;goto _getch
;_procch
        mov ah,0a
        mov dx,cx ;preserve bit count & ascii char
        mov cx,1
        int 10 ;send typed digit to console
        mov cx,dx ;restore bit count & ascii char
        shl cl,1 ;shift to make room for new bit
        and al,1 ;convert ascii "0" and "1" to binary 0/1
        or cl,al ;put the new bit in the lsb of cl
        inc ch ;increment bit counter
        cmp ch,8
        jnz 010e ;goto _getch
;_out
        mov dl,cl ;move ascii char to dl for output on int 21
        mov ah,0a
        mov al,bl ;move original char to al for output
        mov cx,1
        int 10 ;restore the character that we overwrote
        mov ah,02
        int 21 ;print ascii char
        jmp 0106 ;goto _begin
;_quit
        mov ah,03
        xor bh,bh
        int 10 ;get cursor position
        mov ah,08
        int 10 ;preserve character under cursor
        mov ah,02
        mov bl,al
        mov cx,dx
        mov dl,1a
        int 21 ;send ^z
        mov dx,cx
        int 10 ;restore cursor position
        mov ah,0a
        mov al,bl
        mov cx,1
        int 10 ;restore character under cursor
        mov ah,4c
        int 21 ;return to dos
;_ASCIIZ
        db "bin2asc.com",0
;_compile
        MOV AX,CS
        MOV DS,AX
        MOV AH,3C
        XOR CX,CX
        MOV DX,0172 ;_ASCIIZ
        INT 21
        MOV BX,AX
        MOV CX,0172 ;_ASCIIZ
        MOV DX,0100
        SUB CX,DX
        MOV AH,40
        INT 21
        MOV AH,3E
        INT 21
        MOV AX,4C01
        INT 21
 
r ip
17e
g
q
 
:exists
echo You don't need to run this. Run BIN2ASC.COM instead.
goto run
 
:batch
if exist bin2asc.com goto exists
 
if exist %0 goto extension
debug < %0.bat
goto run
 
:extension
debug < %0
 
:run
pause
cls
bin2asc.com

Assembly: Copy and paste into Notepad. Save as "bin2asc-asm.bat" (include the quotes to force the extension). Run the batch file in Windows by double-clicking or by executing it from the command prompt. On its first run, the batch file will run debug.exe and assemble the bin2asc.com executable in the current directory. After assembling the executable the batch will launch it. (Subsequently you can launch the executable without need for the batch file.)

Use: Type or paste (using the sys menu on the command prompt window) binary into the DOS window. All characters other than '1', '0', Esc, and ^Z will be ignored (this allows the program to be forgiving of spaces or newline characters in the binary). Every 8 binary digits will be converted to the corresponding ASCII character. Use the sys menu to copy the output (if needed). Esc or ^Z exit.

User Journal

Journal Journal: ASCII-to-binary (80x86)

ASCII-to-binary in 80x86 assembly (oblig: Binary-to-ASCII)

@echo off
goto batch
 
a
        mov ax,cs
        mov ds,ax
        xor ch,ch ;initialize column counter
;_newchar
        mov ah,08
        int 21 ;get a key
        cmp al,1b ;check for esc
        jz 0159 ;goto _quit
        cmp al,1a ;check for ^z
        jz 0159 ;goto _quit
        mov ah,0a
        xor bh,bh
        mov dh,ch ;preserve column counter
        mov cx,1
        int 10 ;send to console in case output is redirected
        mov ch,dh ;restore column counter
        mov cl,8
        mov ah,02
;_nextbit
        mov dl,30 ;set output char to "0"
        shl al,1
        jnb 012b ;goto _iszero
        inc dl ;change output char to "1"
;_iszero
        mov bl,al ;preserve input char
        int 21 ;print "0" or "1"
        mov al,bl ;restore input char
        dec cl ;decrement the bit counter
        jnz 0123 ;goto _nextbit
        add ch,8 ;increase the column counter
        add ch,[0180] ;add _padlen
        and ch,7f ;don't allow ch to go above 127
        cmp ch,47 ;see if we're overflowing the line
        jnb 014d ;goto _crlf
        mov ah,09
        mov dx,017e ;address of _padding
        int 21 ;print padding string
        jmp 0106 ;goto _newchar
;_crlf
        xor ch,ch ;reset the column counter
        mov dl,0d
        int 21 ;print cr
        mov dl,0a
        int 21 ;print lf
        jmp 0106 ;goto _newchar
;_quit
        mov ah,03
        xor bh,bh
        int 10 ;get cursor position
        mov ah,08
        int 10 ;preserve character under cursor
        mov ah,02
        mov bl,al
        mov cx,dx
        mov dl,1a
        int 21 ;send ^z
        mov dx,cx
        int 10 ;restore cursor position
        mov ah,0a
        mov al,bl
        mov cx,1
        int 10 ;restore character under cursor
        mov ah,4c
        int 21 ;return to dos
;_padding
        db " ","$"
;_padlen
        db 1
;_ASCIIZ
        db "asc2bin.com",0
;_compile
        MOV AX,CS
        MOV DS,AX
        MOV AH,3C
        XOR CX,CX
        MOV DX,0181 ;_ASCIIZ
        INT 21
        MOV BX,AX
        MOV CX,0181 ;_ASCIIZ
        MOV DX,0100
        SUB CX,DX
        MOV AH,40
        INT 21
        MOV AH,3E
        INT 21
        MOV AX,4C01
        INT 21
 
r ip
18d
g
q
 
:exists
echo You don't need to run this. Run ASC2BIN.COM instead.
goto run
 
:batch
if exist asc2bin.com goto exists
 
if exist %0 goto extension
debug < %0.bat
goto run
 
:extension
debug < %0
 
:run
pause
cls
asc2bin.com

Assembly: Copy and paste into Notepad. Save as "asc2bin-asm.bat" (include the quotes to force the extension). Run the batch file in Windows by double-clicking or by executing it from the command prompt. On its first run, the batch file will run debug.exe and assemble the asc2bin.com executable in the current directory. After assembling the executable the batch will launch it. (Subsequently you can launch the executable without need for the batch file.)

Use: Type or paste (using the sys menu on the command prompt window) into the DOS window. Use the sys menu to copy the output. Esc or ^Z exit.

User Journal

Journal Journal: Handy bookmarklet...

javascript:var d=document.getElementsByTagName('div');for(var i=0;i<d.length;i++)if(d[i].className=='oneline'){document.getElementById(d[i].id.split('_').join('_link_')).onclick();i=d.length;}void(0);

I call it "Scroll to first abbreviated post". That said, you should probably be able to figure out what it does.

Slashdot Top Deals

Suggest you just sit there and wait till life gets easier.

Working...