# 8088 assembly checksum implementation

The following 8088/8086 assembly program tests the modular-sum checksum of a block of data. I suspect it could be tighter; can anyone do it in fewer bytes?

31        xor        ax,ax          ; zero the sum
c0
bb        mov        bx,2000h        ; count 8kb of ROM
00
20
4b        dec        bx             ; start at the top
02        add        al,[bx]        ; add the current byte to the total
07
85        test       bx,bx          ; see if we're at the bottom yet
db
75        jnz        -7             ; loop while not done
f9
84        test       al,al          ; sum should be 0
c0
74        jz         1              ; if sum is good, continue with program
01
f4        hlt                       ; if sum is bad, stop

• If that is intended to check 8k, shouldn't that be 2000h instead of just 2000? Also, you could rework the code to use the flags that get set by dec to figure out if you should keep looping rather than doing test. Jun 4, 2017 at 3:40
• Why do you have to do cld? Is there unknown code that executes before this that has a habit of changing and not restoring this? I'd certainly expect the power-on default for any 8086 chip to be cld. Jun 5, 2017 at 1:06
• I'd say not. Code like this is often reused and having cld versus omitting it means that you trade off a single byte for the potential future pain of having things run just fine most of the time until some other function is called that changes the direction flag before this code is invoked. Good luck untangling that runtime nightmare. I'd rather pay the price for the byte and the additional clarity, but that's just me. Jun 5, 2017 at 15:46
• Please do not modify the question to reflect changes made in response to answers or comments. Those changes would actually make the answers invalid. This is site policy. If you want a review of your updated code, you have to ask a new question. Jun 5, 2017 at 15:52
• "Am I being too cautious?" - I'd say it depends on your environment. If you can feel confident about the code that is being executed before you and are desperate for that 1 more byte... Jun 5, 2017 at 21:55

I'm not absolutely certain (I haven't run it through an assembler or checked against an instruction chart), but I believe this may be a byte shorter:

    xor dl, dl
xor si, si
mov cx, 2000h
again:
lodsb       ; load value, increment SI
add dl, al  ; set z flag based on result of addition
loop again  ; decrement CX, jump if NZ, *without* affecting flags

jz good     ; Z flag still has result of addition above
hlt
good:

• Are you sure about that comma after loop? Jun 4, 2017 at 12:21
• This might need a cld instruction to assure that lodsb increments SI. Jun 4, 2017 at 12:49
• @Edward: well, it should probably at least have a comment saying that it assumes the D flag is clear (but unless otherwise specified, that is normally a pretty safe assumption). Jun 4, 2017 at 16:04
• @DavidWohlferd: Oops. Yes, at least with most assemblers that would be wrong. Jun 4, 2017 at 16:06
• I think it's actually two bytes shorter than the original, and a byte shorter than David's modification, but that's without the cld. Jun 4, 2017 at 19:32

To answer my own question, this version (which incorporates suggestions from David Wohlferd in the comments) is one byte shorter:

a0      mov     al,[0000h]      ; the loop skips byte 0000, so add it here
00
00
bb      mov     bx,1fffh        ; count 8kb of ROM
ff
1f
02      add     al,[bx]         ; add current byte to the total, top->bottom
07
4b      dec     bx
75      jnz     -5              ; loop while not done
fb
84      test    al,al           ; sum should be 0
c0
74      jz      1               ; if sum is good, continue with program
01
f4      hlt                     ; if sum is bad, stop

• I was going to recommend using xor al, al to clear the register (some processors optimize for that), but I wonder if mov al, ds:1fff would work? I suspect it wouldn't save you (or cost you) any bytes, but it would reduce the number of loops needed by 1 (mov bx, 1ffeh). Jun 4, 2017 at 12:15
• The 8088 certainly doesn't optimize for XOR to clear registers. It doesn't have register renaming, and doesn't need to break any dependencies. It isn't nearly that complicated of a chip. :-) Of course, XOR to clear a register is still preferable over MOV because it is 1 byte shorter! And reducing the code size, as you appear to already know, is a big deal when optimizing for the 8088. (And 386SX.) Jun 7, 2017 at 12:25
• By the way, just as a code style thing, I would strongly encourage you to use labels as branch targets, rather than hard-coding numerical offsets. Not only does this make the code easier to read at a glance, without having to count bytes, but the numerical offsets are kind of ambiguous, since many assemblers tend to represent them differently than Intel's documentation does. It doesn't change the size of the code or anything to use labels; the assembler will generate identical code. Jun 7, 2017 at 12:27
• Thanks for the feedback. I'm still learning assembly language, and I haven't actually had to use an assembler yet. I just type the bytecodes directly into a file with a hex editor. I'm getting pretty good at reading the raw hex. Jun 7, 2017 at 21:29
• Ah, I see. Well then you are more hardcore than me. :-) Do consider using an assembler and making your life easier. Writing quality, readable assembly code is hard enough. Doing it with a hex editor is just masochism. On retro machines, MASM and TASM are excellent options, usually available on "abandonware" sites. I don't personally see any ethical problems with that, especially with MASM if you own a modern license for a Microsoft development product like Visual Studio. If you prefer free software, NASM and YASM are also excellent choices, and you can do retro-dev from a modern box. Jun 8, 2017 at 8:57