diff options
author | Damian Yerrick <git@pineight.com> | 2020-04-14 12:02:45 -0400 |
---|---|---|
committer | Damian Yerrick <git@pineight.com> | 2020-04-14 12:02:45 -0400 |
commit | e1307134920e8c020a19a9c66117012c80194b61 (patch) | |
tree | fbc662fa262ab76b081a1ea8ec991f6f180f3681 /Optimizing-assembly-code.md | |
parent | f3aa34c74561eff5fc66905b4611c6450e519228 (diff) |
Fix byte/cycle in "Multiply `hl` by 2"; explain principle of sbc a; replace FOO and BAR with more locally meaningful CVAL and NCVAL
Diffstat (limited to 'Optimizing-assembly-code.md')
-rw-r--r-- | Optimizing-assembly-code.md | 84 |
1 files changed, 50 insertions, 34 deletions
diff --git a/Optimizing-assembly-code.md b/Optimizing-assembly-code.md index a608c15..2c308b7 100644 --- a/Optimizing-assembly-code.md +++ b/Optimizing-assembly-code.md @@ -189,15 +189,15 @@ But do: ### Set `a` to one constant or another depending on the carry flag -(The example sets `a` to `FOO` if the carry flag is set (`c`), or `BAR` is the carry flag is not set (`nc`).) +(The example sets `a` to `CVAL` if the carry flag is set (`c`), or `NCVAL` is the carry flag is not set (`nc`).) Don't do: ```asm ; 6 bytes, 6 or 7 cycles - ld a, FOO + ld a, CVAL jr c, .carry - ld a, BAR + ld a, NCVAL .carry ``` @@ -205,9 +205,9 @@ And don't do: ```asm ; 6 bytes, 6 or 7 cycles - ld a, BAR + ld a, NCVAL jr nc, .no_carry - ld a, FOO + ld a, CVAL .no_carry ``` @@ -215,64 +215,81 @@ And if either is 0, don't do: ```asm ; 5 bytes, 5 or 6 cycles - ld a, FOO ; nor BAR + ld a, CVAL ; nor NCVAL jr c, .carry ; nor jr nc xor a .carry ``` -But do: +Instead use `sbc a`, which copies the carry flag to all bits of `a`. Thus do: ```asm ; 5 bytes, 5 cycles - sbc a ; if carry, then $ff, else 0 - and FOO - BAR ; $ff becomes FOO - BAR, 0 stays 0 - add BAR ; FOO - BAR becomes FOO, 0 becomes BAR + sbc a ; if carry, then $ff, else 0 + and CVAL - NCVAL ; $ff becomes CVAL - NCVAL, 0 stays 0 + add NCVAL ; CVAL - NCVAL becomes CVAL, 0 becomes NCVAL ``` Or do: ```asm ; 5 bytes, 5 cycles - sbc a ; if carry, then $ff, else 0 - and FOO ^ BAR ; $ff becomes FOO ^ BAR, 0 stays 0 - xor BAR ; FOO ^ BAR becomes FOO, 0 becomes BAR + sbc a ; if carry, then $ff, else 0 + and CVAL ^ NCVAL ; $ff becomes CVAL ^ NCVAL, 0 stays 0 + xor NCVAL ; CVAL ^ NCVAL becomes CVAL, 0 becomes NCVAL ``` -If `FOO` is 0 (i.e. set `a` to 0 if carry), then do: +If `NCVAL` is 0 (i.e. set `a` to 0 if not carry), then do: + +```asm + ; 3 bytes, 3 cycles + sbc a ; if carry, then $ff, else 0 + and CVAL ; $ff becomes CVAL, 0 stays 0 +``` + +If `CVAL` is 0 (i.e. set `a` to 0 if carry), invert carry and do the same: ```asm ; 4 bytes, 4 cycles - ccf ; invert carry flag - sbc a ; if originally carry, then 0, else $ff - and BAR ; 0 stays 0, $ff becomes BAR + ccf ; invert carry flag + sbc a ; if originally carry, then 0, else $ff + and NCVAL ; 0 stays 0, $ff becomes NCVAL ``` -If `BAR` is 0 (i.e. set `a` to 0 if not carry), then do: +If `CVAL` is $FF (i.e. set `a` to $FF if carry), then do: ```asm ; 3 bytes, 3 cycles - sbc a ; if carry, then $ff, else 0 - and FOO ; $ff becomes FOO, 0 stays 0 + sbc a ; if carry, then $ff, else 0 + or NCVAL ; $ff stays $ff, $00 becomes NCVAL +``` + +If `NCVAL` is $FF (i.e. set `a` to $FF if not carry), invert carry and do the same: + +```asm + ; 4 bytes, 4 cycles + ccf ; invert carry flag + sbc a ; if originally carry, then 0, else $ff + or CVAL ; $00 becomes CVAL, $ff stays $ff ``` -If `FOO` equals `BAR - 1`, then do: +If `CVAL` equals `NCVAL - 1`, then do: ```asm ; 3 bytes, 3 cycles - sbc a ; if carry, then $ff aka -1, else 0 - add BAR ; -1 becomes BAR - 1 aka FOO, 0 becomes BAR + sbc a ; if carry, then $ff aka -1, else 0 + add NCVAL ; -1 becomes NCVAL - 1 aka CVAL, 0 becomes NCVAL ``` -If `FOO` equals `BAR - 2`, then do: +If `CVAL` equals `NCVAL - 2`, then do: ```asm ; 3 bytes, 3 cycles - sbc a ; if carry, then $ff aka -1, else 0; doesn't change the carry flag - sbc -BAR ; -1 becomes BAR - 2 aka FOO, 0 becomes BAR + sbc a ; if carry, then $ff aka -1, else 0; doesn't change the carry flag + sbc -NCVAL ; -1 becomes NCVAL - 2 aka CVAL, 0 becomes NCVAL ``` -If `FOO` is 0 and `BAR` is 1 (i.e. set `a` to 0 if carry, or 1 if not carry), then do: +If `CVAL` is 0 and `NCVAL` is 1 (i.e. set `a` to 0 if carry, or 1 if not carry), then do: ```asm ; 2 bytes, 2 cycles @@ -281,7 +298,6 @@ If `FOO` is 0 and `BAR` is 1 (i.e. set `a` to 0 if carry, or 1 if not carry), th ``` - ### Shift `a` right by 3 bits Don't do: @@ -394,7 +410,7 @@ But do: Don't do: ```asm - ; 6 bytes, 6 cycles + ; 4 bytes, 4 cycles sla l rl h ``` @@ -521,7 +537,7 @@ Don't do: ```asm ; 8 bytes, 10 cycles - ld a, [Address] + ld a, [Address] ; LSB first ld l, a ld a, [Address+1] ld h, a @@ -541,7 +557,7 @@ And don't do: ```asm ; 8 bytes, 10 cycles - ld a, [Address] + ld a, [Address] ; MSB first ld h, a ld a, [Address+1] ld l, a @@ -730,7 +746,7 @@ Or do: cp 1 ; 2 bytes, 2 cycles ``` -If you don't care about the value in `a`: +If you don't care about carry or the value in `a`: ```asm @@ -761,7 +777,7 @@ with: cp $ff ; 2 bytes, 2 cycles ``` -If you don't care about the value in `a`: +If you don't care about carry or the value in `a`: ```asm inc a ; 1 byte, 1 cycle, increments a @@ -912,7 +928,7 @@ Function: ret ``` -You can still `call Function` elsewhere, but one tail call can be optimized into a fallthrough. +Fallthrough is what you get when you combine inlining with tail calls. You can still `call Function` elsewhere, but one tail call can be optimized into a fallthrough. ## Conditional fallthrough |