flat assembler
Message board for the users of flat assembler.
 Home   FAQ   Search   Register 
 Profile   Log in to check your private messages   Log in 
flat assembler > DOS > BYTEFIX -- change a hex byte in a binary file

Author
Thread Post new topic Reply to topic
rugxulo



Joined: 09 Aug 2005
Posts: 2109
Location: Usono (aka, USA)
BYTEFIX -- change a hex byte in a binary file
Not quite a full hex editor, but it's very small and usable inside .BAT files (automated/scriptable). It tries to check for most common errors, too.

Alas, it could definitely be written "better", but for now this will have to do.


Code:

; BYTEFIX.ASM -- change a hex byte in a binary file
;
; rugxulo _AT_ gmail
;
; public domain, free for any use, nenies proprajho, "Christus Rex!"


ARGC=80h
ARGV=81h
BYTE1=ARGV+1+8+1
CR=13
FILENAME=ARGV+1+8+1+2+1+2+1
LF=10
MINARGC=15+1

CLOSEFILE=3Eh
GOODBYE=4Ch
OPENFILERW=3D02h
READFILE=3Fh
SEEKSETFILE=4200h
WRITEFILE=40h
WRITESTR=9

DOS equ int 21h

b equ byte
w equ word


; section .text

org 100h ; DOS .COM

Main:
  call fixargs
  cmp b[ARGC],MINARGC
  jae .okay
  mov ah,WRITESTR
  mov dx,usagemsg
  DOS
  mov b[errlvl],255
  jmp Fino
.okay:
  mov si,ARGV+1
  call scanofs
  jc Fino
  call fixbyte
Fino:
  mov ah,GOODBYE
  mov al,b[errlvl]
  DOS
; end Main


; proc
fixargs:
  xor ch,ch
  mov cl,b[ARGC]
  jcxz .ret
  push cx
  call stripblanks
  pop cx
  mov si,ARGV+1
  mov di,si
.loop:
  lodsb
  push cx
  mov bx,'az'
  push bx
  call rangecheck
  pop cx
  sbb bl,bl
  or bl,not ' '
  and al,bl
  stosb
  loop .loop
.ret:
  ret
; endp


; proc
stripblanks:
  mov di,ARGV
  lea si,[di+1]
  inc cx
  mov al,' '
  rep scasb
  dec di
  mov b[ARGC],cl
  xchg si,di
  push cx cx
  rep movsb
  pop cx di
  add di,ARGV
  mov al,' '
  std
  rep scasb
  cld
  inc cx
  mov b[di+2],0 ; NUL (for ASCIIZ filename)
  mov b[ARGC],cl
  ret
; endp


; proc
fixbyte:
  call getbytes
.open:
  mov ax,OPENFILERW
  mov dx,FILENAME
  DOS
  jc .ret
  mov [handle],ax
.seek:
  call seekbyte
  jc .close
.read:
  mov ah,READFILE
  mov bx,[handle]
  mov cx,1
  mov dx,foundbyte
  DOS
  jc .close
.compare:
  mov al,[foundbyte]
  cmp al,b[oldbyte]
  jnz .close
  call seekbyte
.write:
  mov ah,WRITEFILE
  mov bx,[handle]
  mov cx,1
  mov dx,newbyte
  DOS
  jc .close
  mov b[errlvl],0
.close:
  mov ah,CLOSEFILE
  mov bx,[handle]
  DOS
.ret:
  ret
; endp


; proc
seekbyte:
  mov ax,SEEKSETFILE
  mov bx,[handle]
  mov cx,w[ofs+2]
  mov dx,w[ofs]
  DOS
  ret
;endp


; proc
getbytes:
  mov si,BYTE1
  call hexbyte
  mov [oldbyte],al
  call hexbyte
  mov [newbyte],al
  ret
; endp


; proc
hexbyte:
  lodsb
  call ishex
  jc .ret
  call asc2hex
  mov cl,4
  shl al,cl
  mov dl,al
  lodsb
  push dx
  call ishex
  pop dx
  jc .ret
  call asc2hex
  add dl,al
  inc si
  xchg ax,dx
.ret:
  ret
; endp


; proc
scanofs:
  mov cx,8
.load:
  lodsb
  push cx
  call ishex
  pop cx
  jc .ret
  push cx
  call asc2hex
  pop cx
.adjust:
  push ax cx
  mov ax,w[ofs]
  mov dx,w[ofs+2]
  mov cl,4
.shift:
  rcl ax,1
  rcl dx,1
  loop .shift
  pop cx
  mov w[ofs],ax
  mov w[ofs+2],dx
.add:
  pop ax
  xor ah,ah
  add w[ofs],ax
  adc w[ofs+2],0
.continue:
  loop .load
.ret:
  ret
; endp


; proc
asc2hex:
  cmp al,40h
  adc al,69h
  daa
  mov ah,al
  and al,15
  mov cl,4
  shr ah,cl
  aad
  ret
; endp


; proc
ishex:
  mov cx,'09'
  push cx
  call rangecheck
  sbb bh,bh

; mov cx,'af'
; push cx
; call rangecheck
; sbb bl,bl
; and bh,bl

  mov cx,'AF'
  push cx
  call rangecheck
  sbb bl,bl
  and bh,bl

  neg bh
  clc
  lahf
  or ah,bh
  sahf

  ret       ; return CF if not valid hex char
; endp


; proc
rangecheck; in: (upper_limit shl 8) + lower_limit
  pop bp
  pop dx    ; mov dx,[sp+2]
  push bp
.check:
  cmp al,dl
  sbb ch,ch
  inc dh
  cmp al,dh
  cmc
  sbb dl,dl
  or dl,ch
  cmp dl,1  ; set CF if DL == 0
  cmc       ; return NC if AL within valid range
  ret
; endp


; section .data

errlvl db 1
handle dw 0
ofs    dd 0
usagemsg db CR,LF,'Usage:  bytefix.com CaFe5150 1a 2b file.dat',CR,LF,'$'


; section .bss

oldbyte rb 1
newbyte rb 1
foundbyte rb 1

; EOF


Post 08 Mar 2017, 01:32
View user's profile Send private message Visit poster's website Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2109
Location: Usono (aka, USA)
Re: BYTEFIX -- change a hex byte in a binary file

rugxulo wrote:

Alas, it could definitely be written "better", but for now this will have to do.




Code:

--- bytefix.old 2017-03-07 14:13:52 -0600
+++ bytefix.new 2017-03-10 12:19:20 -0600
@@ -40,3 +40,3 @@
   DOS
-  mov b[errlvl],255
+  neg b[errlvl]
   jmp Fino
@@ -48,4 +48,3 @@
 Fino:
-  mov ah,GOODBYE
-  mov al,b[errlvl]
+  mov ax,w[errlvl]
   DOS
@@ -109,2 +108,5 @@
   call getbytes
+.issame:
+  cmp al,[di-2]
+  jz .ret
 .open:
@@ -161,6 +163,7 @@
   mov si,BYTE1
+  mov di,oldbyte
   call hexbyte
-  mov [oldbyte],al
-  call hexbyte
-  mov [newbyte],al
+  stosb
+  call hexbyte ; newbyte
+  stosb
   ret
@@ -206,12 +209,8 @@
   push ax cx
-  mov ax,w[ofs]
-  mov dx,w[ofs+2]
   mov cl,4
 .shift:
-  rcl ax,1
-  rcl dx,1
+  rcl w[ofs],1
+  rcl w[ofs+2],1
   loop .shift
   pop cx
-  mov w[ofs],ax
-  mov w[ofs+2],dx
 .add:
@@ -261,7 +260,3 @@
 
-  neg bh
-  clc
-  lahf
-  or ah,bh
-  sahf
+  shr bh,1
 
@@ -292,3 +287,3 @@
 
-errlvl db 1
+errlvl db 1GOODBYE
 handle dw 0


Post 10 Mar 2017, 20:39
View user's profile Send private message Visit poster's website Reply with quote
rugxulo



Joined: 09 Aug 2005
Posts: 2109
Location: Usono (aka, USA)
Made a (very) few fixes and improvements. Is it worth keeping the original version (and/or diff)? Meh, but for now, for completeness, I'll leave 'em "as is".


Code:

; BYTEFIX.ASM -- change a hex byte in a binary file
;
; rugxulo _AT_ gmail
;
; public domain, free for any use, nenies proprajho, "Christus Rex!"


ARGC=80h
ARGV=81h
BYTE1=ARGV+1+8+1
CR=13
FILENAME=ARGV+1+8+1+2+1+2+1
LF=10
MINARGC=15+1

CLOSEFILE=3Eh
GOODBYE=4Ch
OPENFILERW=3D02h
READFILE=3Fh
SEEKSETFILE=4200h
WRITEFILE=40h
WRITESTR=9

DOS equ int 21h

b equ byte
w equ word

macro proc name {
  if used name
name:
}
endp fix end if


; section .text

org 100h

Main:
  call fixargs
  cmp b[ARGC],MINARGC
  jae .okay
  mov ah,WRITESTR
  mov dx,usagemsg
  DOS
  neg [errlvl]
  jmp Fino
.okay:
  mov si,ARGV+1
  call scanofs
  jc Fino
  call fixbyte
Fino:
  mov ax,w[errlvl]
  DOS
; end Main


proc fixargs
  xor ch,ch
  mov cl,b[ARGC]
  jcxz .ret
  push cx
  call stripblanks
  pop cx
  mov si,ARGV+1
  mov di,si
.loop:
  lodsb
  push cx
  mov bx,'az'
  push bx
  call rangecheck
  pop cx
  sbb bl,bl
  or bl,not ' '
  and al,bl
  stosb
  loop .loop
.ret:
  ret
endp


proc stripblanks
  mov di,ARGV
  lea si,[di+1]
  inc cx
  mov al,' '
  rep scasb
  dec di
  mov b[ARGC],cl
  xchg si,di
  push cx cx
  rep movsb
  pop cx di
  add di,ARGV
  mov al,' '
  std
  rep scasb
  cld
  inc cx
  mov b[di+2],0 ; NUL (for ASCIIZ filename)
  mov b[ARGC],cl
  ret
endp


proc fixbyte
  cmp b[BYTE1],'?'
  jz .open
  call getbytes
  jc .ret
.issame:
  cmp al,[di-2]
  jz .ret
.open:
  mov ax,OPENFILERW
  mov dx,FILENAME
  DOS
  jc .ret
  mov [handle],ax
.seek:
  call seekbyte
  jc .close
.read:
  mov ah,READFILE
  mov bx,[handle]
  mov cx,1
  mov dx,foundbyte
  DOS
  jc .close
.query:
  cmp b[BYTE1],'?'
  jnz .compare
  mov al,[foundbyte]
  mov [errlvl],al
  jmp .close
.compare:
  mov al,[foundbyte]
  cmp al,b[oldbyte]
  jnz .close
  call seekbyte
.write:
  mov ah,WRITEFILE
  mov bx,[handle]
  mov cx,1
  mov dx,newbyte
  DOS
  jc .close
  dec [errlvl]
.close:
  mov ah,CLOSEFILE
  mov bx,[handle]
  DOS
.ret:
  ret
endp


proc seekbyte
  mov ax,SEEKSETFILE
  mov bx,[handle]
  mov cx,w[ofs+2]
  mov dx,w[ofs]
  DOS
  ret
endp


proc getbytes
  mov si,BYTE1
  mov di,oldbyte
  call hexbyte
  jc .ret
  call hexbyte ; newbyte
.ret:
  ret
endp


proc hexbyte
  lodsb
  call ishex
  jc .ret
  call asc2hex
  mov cl,4
  shl al,cl
  mov dl,al
  lodsb
  push dx
  call ishex
  pop dx
  jc .ret
  call asc2hex
  add dl,al
  inc si
  xchg ax,dx
  stosb
.ret:
  ret
endp


proc scanofs
  mov cx,8
.load:
  lodsb
  push cx
  call ishex
  pop cx
  jc .ret
  push cx
  call asc2hex
  pop cx
.adjust:
  push ax cx
  mov cl,4
.shift:
  rcl w[ofs],1
  rcl w[ofs+2],1
  loop .shift
  pop cx
.add:
  pop ax
  xor ah,ah
  add w[ofs],ax
  adc w[ofs+2],0
.continue:
  loop .load
.ret:
  ret
endp


proc asc2hex
  cmp al,40h
  adc al,69h
  daa
  mov ah,al
  and al,15
  mov cl,4
  shr ah,cl
  aad
  ret
endp


proc ishex
  mov cx,'09'
  push cx
  call rangecheck
  sbb bh,bh

; mov cx,'af'
; push cx
; call rangecheck
; sbb bl,bl
; and bh,bl

  mov cx,'AF'
  push cx
  call rangecheck
  sbb bl,bl
  and bh,bl

  shr bh,1

  ret       ; return CF if not valid hex char
endp


proc rangecheck
            ; in: (upper_limit shl 8) + lower_limit
  pop bp
  pop dx    ; mov dx,[sp+2]
  push bp
.check:
  cmp al,dl
  sbb ch,ch
  inc dh
  cmp al,dh
  cmc
  sbb dl,dl
  or dl,ch
  cmp dl,1  ; set CF if DL == 0
  cmc       ; return NC if AL within valid range
  ret
endp


; section .data

errlvl db 1GOODBYE
handle dw 0
ofs    dd 0
usagemsg db CR,LF,'Usage:  bytefix.com CaFe5150 Ed A1 file.dat',CR,LF,'$'


; section .bss

oldbyte rb 1
newbyte rb 1
foundbyte rb 1

; EOF


Post 16 Mar 2017, 03:13
View user's profile Send private message Visit poster's website Reply with quote
Display posts from previous:
Post new topic Reply to topic

Jump to:  


< Last Thread | Next Thread >

Forum Rules:
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001-2005 phpBB Group.

Main index   Download   Documentation   Examples   Message board
Copyright © 2004-2016, Tomasz Grysztar.