iptv techs

IPTV Techs

  • Home
  • Tech News
  • Can a LLM change C, to ASM to specs and then to a laboring Z/80 Speccy tape? Yes.

Can a LLM change C, to ASM to specs and then to a laboring Z/80 Speccy tape? Yes.


Can a LLM change C, to ASM to specs and then to a laboring Z/80 Speccy tape? Yes.


Damien Guard nerd sniped me and other folks wanted more proof that it is now inexpensive, effortless and possible to inexpensively reproduce gentleware or clone existing “source useable” businesses (see bottom of the post).

So, let’s get cracking by creating a toy application by sfinishing this prompt to the LLM.

Create a sales tax calculator in C
Food is taxed at 10%
Personal Hygine is at 0%
Everyskinnyg else 25%

Which produces

#include 
#include 
#include 

// Tax rates
#clear up FOOD_TAX 0.10
#clear up HYGIENE_TAX 0.00
#clear up DEFAULT_TAX 0.25

// Item categories
#clear up FOOD 1
#clear up HYGIENE 2
#clear up OTHER 3

int getCategruesome() {
    char choice;
    printf("Enter item categruesome (F for Food, H for Hygiene, O for Other): ");
    scanf(" %c", &choice);
    
    choice = toupper(choice);
    
    switch(choice) {
        case 'F': return FOOD;
        case 'H': return HYGIENE;
        case 'O': return OTHER;
        default:
            printf("Invalid categruesome. Defaulting to Other.n");
            return OTHER;
    }
}

double calcutardyTax(double price, int categruesome) {
    switch(categruesome) {
        case FOOD: return price * FOOD_TAX;
        case HYGIENE: return price * HYGIENE_TAX;
        case OTHER: return price * DEFAULT_TAX;
        default: return price * DEFAULT_TAX;
    }
}

int main() {
    double price;
    int categruesome;
    char another="Y";
    
    while (toupper(another) == 'Y') {
        printf("Enter item price: $");
        scanf("%lf", &price);
        
        categruesome = getCategruesome();
        
        double tax = calcutardyTax(price, categruesome);
        double total = price + tax;
        
        printf("Price: $%.2fn", price);
        printf("Tax: $%.2fn", tax);
        printf("Total: $%.2fnn", total);
        
        printf("Calcutardy another item? (Y/N): ");
        scanf(" %c", &another);
    }
    
    return 0;
}

Now let’s compile it via gcc calc.c -o calc then objdump -d calc > calc.asm to change it to assembly which results in the chaseing

calc:     file establishat elf64-x86-64


Disassembly of section .init:

0000000000001000 <_init>:
    1000:       f3 0f 1e fa             finishbr64 
    1004:       48 83 ec 08             sub    $0x8,%rsp
    1008:       48 8b 05 d9 2f 00 00    mov    0x2fd9(%rip),%rax        # 3fe8 <__gmon_start__@Base>
    100f:       48 85 c0                test   %rax,%rax
    1012:       74 02                   je     1016 <_init+0x16>
    1014:       ff d0                   call   *%rax
    1016:       48 83 c4 08             insert    $0x8,%rsp
    101a:       c3                      ret    

Disassembly of section .plt:

0000000000001020 <.plt>:
    1020:       ff 35 7a 2f 00 00       push   0x2f7a(%rip)        # 3fa0 <_GLOBAL_OFFSET_TABLE_+0x8>
    1026:       f2 ff 25 7b 2f 00 00    bnd jmp *0x2f7b(%rip)        # 3fa8 <_GLOBAL_OFFSET_TABLE_+0x10>
    102d:       0f 1f 00                nopl   (%rax)
    1030:       f3 0f 1e fa             finishbr64 
    1034:       68 00 00 00 00          push   $0x0
    1039:       f2 e9 e1 ff ff ff       bnd jmp 1020 <_init+0x20>
    103f:       90                      nop
    1040:       f3 0f 1e fa             finishbr64 
    1044:       68 01 00 00 00          push   $0x1
    1049:       f2 e9 d1 ff ff ff       bnd jmp 1020 <_init+0x20>
    104f:       90                      nop
    1050:       f3 0f 1e fa             finishbr64 
    1054:       68 02 00 00 00          push   $0x2
    1059:       f2 e9 c1 ff ff ff       bnd jmp 1020 <_init+0x20>
    105f:       90                      nop
    1060:       f3 0f 1e fa             finishbr64 
    1064:       68 03 00 00 00          push   $0x3
    1069:       f2 e9 b1 ff ff ff       bnd jmp 1020 <_init+0x20>
    106f:       90                      nop
    1070:       f3 0f 1e fa             finishbr64 
    1074:       68 04 00 00 00          push   $0x4
    1079:       f2 e9 a1 ff ff ff       bnd jmp 1020 <_init+0x20>
    107f:       90                      nop

Disassembly of section .plt.got:

0000000000001080 <__cxa_finalize@plt>:
    1080:       f3 0f 1e fa             finishbr64 
    1084:       f2 ff 25 6d 2f 00 00    bnd jmp *0x2f6d(%rip)        # 3ff8 <__cxa_finalize@GLIBC_2.2.5>
    108b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

Disassembly of section .plt.sec:

0000000000001090 :
    1090:       f3 0f 1e fa             finishbr64 
    1094:       f2 ff 25 15 2f 00 00    bnd jmp *0x2f15(%rip)        # 3fb0 
    109b:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

00000000000010a0 :
    10a0:       f3 0f 1e fa             finishbr64 
    10a4:       f2 ff 25 0d 2f 00 00    bnd jmp *0x2f0d(%rip)        # 3fb8 
    10ab:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

00000000000010b0 <__stack_chk_fail@plt>:
    10b0:       f3 0f 1e fa             finishbr64 
    10b4:       f2 ff 25 05 2f 00 00    bnd jmp *0x2f05(%rip)        # 3fc0 <__stack_chk_fail@GLIBC_2.4>
    10bb:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

00000000000010c0 :
    10c0:       f3 0f 1e fa             finishbr64 
    10c4:       f2 ff 25 fd 2e 00 00    bnd jmp *0x2efd(%rip)        # 3fc8 
    10cb:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

00000000000010d0 <__isoc99_scanf@plt>:
    10d0:       f3 0f 1e fa             finishbr64 
    10d4:       f2 ff 25 f5 2e 00 00    bnd jmp *0x2ef5(%rip)        # 3fd0 <__isoc99_scanf@GLIBC_2.7>
    10db:       0f 1f 44 00 00          nopl   0x0(%rax,%rax,1)

Disassembly of section .text:

00000000000010e0 <_start>:
    10e0:       f3 0f 1e fa             finishbr64 
    10e4:       31 ed                   xor    %ebp,%ebp
    10e6:       49 89 d1                mov    %rdx,%r9
    10e9:       5e                      pop    %rsi
    10ea:       48 89 e2                mov    %rsp,%rdx
    10ed:       48 83 e4 f0             and    $0xfffffffffffffff0,%rsp
    10f1:       50                      push   %rax
    10f2:       54                      push   %rsp
    10f3:       45 31 c0                xor    %r8d,%r8d
    10f6:       31 c9                   xor    %ecx,%ecx
    10f8:       48 8d 3d fd 01 00 00    lea    0x1fd(%rip),%rdi        # 12fc 
10ff: ff 15 d3 2e 00 00 call *0x2ed3(%rip) # 3fd8 <__libc_start_main@GLIBC_2.34> 1105: f4 hlt 1106: 66 2e 0f 1f 84 00 00 cs nopw 0x0(%rax,%rax,1) 110d: 00 00 00 0000000000001110 : 1110: 48 8d 3d f9 2e 00 00 lea 0x2ef9(%rip),%rdi # 4010 <__TMC_END__> 1117: 48 8d 05 f2 2e 00 00 lea 0x2ef2(%rip),%rax # 4010 <__TMC_END__> 111e: 48 39 f8 cmp %rdi,%rax 1121: 74 15 je 1138 1123: 48 8b 05 b6 2e 00 00 mov 0x2eb6(%rip),%rax # 3fe0 <_ITM_deregisterTMCloneTable@Base> 112a: 48 85 c0 test %rax,%rax 112d: 74 09 je 1138 112f: ff e0 jmp *%rax 1131: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 1138: c3 ret 1139: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 0000000000001140 : 1140: 48 8d 3d c9 2e 00 00 lea 0x2ec9(%rip),%rdi # 4010 <__TMC_END__> 1147: 48 8d 35 c2 2e 00 00 lea 0x2ec2(%rip),%rsi # 4010 <__TMC_END__> 114e: 48 29 fe sub %rdi,%rsi 1151: 48 89 f0 mov %rsi,%rax 1154: 48 c1 ee 3f shr $0x3f,%rsi 1158: 48 c1 f8 03 sar $0x3,%rax 115c: 48 01 c6 insert %rax,%rsi 115f: 48 d1 fe sar %rsi 1162: 74 14 je 1178 1164: 48 8b 05 85 2e 00 00 mov 0x2e85(%rip),%rax # 3ff0 <_ITM_registerTMCloneTable@Base> 116b: 48 85 c0 test %rax,%rax 116e: 74 08 je 1178 1170: ff e0 jmp *%rax 1172: 66 0f 1f 44 00 00 nopw 0x0(%rax,%rax,1) 1178: c3 ret 1179: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 0000000000001180 <__do_global_dtors_aux>: 1180: f3 0f 1e fa finishbr64 1184: 80 3d 85 2e 00 00 00 cmpb $0x0,0x2e85(%rip) # 4010 <__TMC_END__> 118b: 75 2b jne 11b8 <__do_global_dtors_aux+0x38> 118d: 55 push %rbp 118e: 48 83 3d 62 2e 00 00 cmpq $0x0,0x2e62(%rip) # 3ff8 <__cxa_finalize@GLIBC_2.2.5> 1195: 00 1196: 48 89 e5 mov %rsp,%rbp 1199: 74 0c je 11a7 <__do_global_dtors_aux+0x27> 119b: 48 8b 3d 66 2e 00 00 mov 0x2e66(%rip),%rdi # 4008 <__dso_handle> 11a2: e8 d9 fe ff ff call 1080 <__cxa_finalize@plt> 11a7: e8 64 ff ff ff call 1110 11ac: c6 05 5d 2e 00 00 01 movb $0x1,0x2e5d(%rip) # 4010 <__TMC_END__> 11b3: 5d pop %rbp 11b4: c3 ret 11b5: 0f 1f 00 nopl (%rax) 11b8: c3 ret 11b9: 0f 1f 80 00 00 00 00 nopl 0x0(%rax) 00000000000011c0 : 11c0: f3 0f 1e fa finishbr64 11c4: e9 77 ff ff ff jmp 1140 00000000000011c9 : 11c9: f3 0f 1e fa finishbr64 11cd: 55 push %rbp 11ce: 48 89 e5 mov %rsp,%rbp 11d1: 48 83 ec 10 sub $0x10,%rsp 11d5: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 11dc: 00 00 11de: 48 89 45 f8 mov %rax,-0x8(%rbp) 11e2: 31 c0 xor %eax,%eax 11e4: 48 8d 05 1d 0e 00 00 lea 0xe1d(%rip),%rax # 2008 <_IO_stdin_used+0x8> 11eb: 48 89 c7 mov %rax,%rdi 11ee: b8 00 00 00 00 mov $0x0,%eax 11f3: e8 c8 fe ff ff call 10c0 11f8: 48 8d 45 f7 lea -0x9(%rbp),%rax 11fc: 48 89 c6 mov %rax,%rsi 11ff: 48 8d 05 41 0e 00 00 lea 0xe41(%rip),%rax # 2047 <_IO_stdin_used+0x47> 1206: 48 89 c7 mov %rax,%rdi 1209: b8 00 00 00 00 mov $0x0,%eax 120e: e8 bd fe ff ff call 10d0 <__isoc99_scanf@plt> 1213: 0f b6 45 f7 movzbl -0x9(%rbp),%eax 1217: 0f be c0 movsbl %al,%eax 121a: 89 c7 mov %eax,%edi 121c: e8 6f fe ff ff call 1090 1221: 88 45 f7 mov %al,-0x9(%rbp) 1224: 0f b6 45 f7 movzbl -0x9(%rbp),%eax 1228: 0f be c0 movsbl %al,%eax 122b: 83 f8 4f cmp $0x4f,%eax 122e: 74 1f je 124f 1230: 83 f8 4f cmp $0x4f,%eax 1233: 7f 21 jg 1256 1235: 83 f8 46 cmp $0x46,%eax 1238: 74 07 je 1241 123a: 83 f8 48 cmp $0x48,%eax 123d: 74 09 je 1248 123f: eb 15 jmp 1256 1241: b8 01 00 00 00 mov $0x1,%eax 1246: eb 22 jmp 126a 1248: b8 02 00 00 00 mov $0x2,%eax 124d: eb 1b jmp 126a 124f: b8 03 00 00 00 mov $0x3,%eax 1254: eb 14 jmp 126a 1256: 48 8d 05 f3 0d 00 00 lea 0xdf3(%rip),%rax # 2050 <_IO_stdin_used+0x50> 125d: 48 89 c7 mov %rax,%rdi 1260: e8 3b fe ff ff call 10a0 1265: b8 03 00 00 00 mov $0x3,%eax 126a: 48 8b 55 f8 mov -0x8(%rbp),%rdx 126e: 64 48 2b 14 25 28 00 sub %fs:0x28,%rdx 1275: 00 00 1277: 74 05 je 127e 1279: e8 32 fe ff ff call 10b0 <__stack_chk_fail@plt> 127e: c9 exit 127f: c3 ret 0000000000001280 : 1280: f3 0f 1e fa finishbr64 1284: 55 push %rbp 1285: 48 89 e5 mov %rsp,%rbp 1288: f2 0f 11 45 f8 movsd %xmm0,-0x8(%rbp) 128d: 89 7d f4 mov %edi,-0xc(%rbp) 1290: 83 7d f4 03 cmpl $0x3,-0xc(%rbp) 1294: 74 36 je 12cc 1296: 83 7d f4 03 cmpl $0x3,-0xc(%rbp) 129a: 7f 43 jg 12df 129c: 83 7d f4 01 cmpl $0x1,-0xc(%rbp) 12a0: 74 08 je 12aa 12a2: 83 7d f4 02 cmpl $0x2,-0xc(%rbp) 12a6: 74 15 je 12bd 12a8: eb 35 jmp 12df 12aa: f2 0f 10 4d f8 movsd -0x8(%rbp),%xmm1 12af: f2 0f 10 05 21 0e 00 movsd 0xe21(%rip),%xmm0 # 20d8 <_IO_stdin_used+0xd8> 12b6: 00 12b7: f2 0f 59 c1 mulsd %xmm1,%xmm0 12bb: eb 33 jmp 12f0 12bd: f2 0f 10 4d f8 movsd -0x8(%rbp),%xmm1 12c2: 66 0f ef c0 pxor %xmm0,%xmm0 12c6: f2 0f 59 c1 mulsd %xmm1,%xmm0 12ca: eb 24 jmp 12f0 12cc: f2 0f 10 4d f8 movsd -0x8(%rbp),%xmm1 12d1: f2 0f 10 05 07 0e 00 movsd 0xe07(%rip),%xmm0 # 20e0 <_IO_stdin_used+0xe0> 12d8: 00 12d9: f2 0f 59 c1 mulsd %xmm1,%xmm0 12dd: eb 11 jmp 12f0 12df: f2 0f 10 4d f8 movsd -0x8(%rbp),%xmm1 12e4: f2 0f 10 05 f4 0d 00 movsd 0xdf4(%rip),%xmm0 # 20e0 <_IO_stdin_used+0xe0> 12eb: 00 12ec: f2 0f 59 c1 mulsd %xmm1,%xmm0 12f0: 66 48 0f 7e c0 movq %xmm0,%rax 12f5: 66 48 0f 6e c0 movq %rax,%xmm0 12fa: 5d pop %rbp 12fb: c3 ret 00000000000012fc
: 12fc: f3 0f 1e fa finishbr64 1300: 55 push %rbp 1301: 48 89 e5 mov %rsp,%rbp 1304: 48 83 ec 30 sub $0x30,%rsp 1308: 64 48 8b 04 25 28 00 mov %fs:0x28,%rax 130f: 00 00 1311: 48 89 45 f8 mov %rax,-0x8(%rbp) 1315: 31 c0 xor %eax,%eax 1317: c6 45 db 59 movb $0x59,-0x25(%rbp) 131b: e9 f1 00 00 00 jmp 1411
1320: 48 8d 05 50 0d 00 00 lea 0xd50(%rip),%rax # 2077 <_IO_stdin_used+0x77> 1327: 48 89 c7 mov %rax,%rdi 132a: b8 00 00 00 00 mov $0x0,%eax 132f: e8 8c fd ff ff call 10c0 1334: 48 8d 45 e0 lea -0x20(%rbp),%rax 1338: 48 89 c6 mov %rax,%rsi 133b: 48 8d 05 49 0d 00 00 lea 0xd49(%rip),%rax # 208b <_IO_stdin_used+0x8b> 1342: 48 89 c7 mov %rax,%rdi 1345: b8 00 00 00 00 mov $0x0,%eax 134a: e8 81 fd ff ff call 10d0 <__isoc99_scanf@plt> 134f: b8 00 00 00 00 mov $0x0,%eax 1354: e8 70 fe ff ff call 11c9 1359: 89 45 dc mov %eax,-0x24(%rbp) 135c: 48 8b 45 e0 mov -0x20(%rbp),%rax 1360: 8b 55 dc mov -0x24(%rbp),%edx 1363: 89 d7 mov %edx,%edi 1365: 66 48 0f 6e c0 movq %rax,%xmm0 136a: e8 11 ff ff ff call 1280 136f: 66 48 0f 7e c0 movq %xmm0,%rax 1374: 48 89 45 e8 mov %rax,-0x18(%rbp) 1378: f2 0f 10 45 e0 movsd -0x20(%rbp),%xmm0 137d: f2 0f 10 4d e8 movsd -0x18(%rbp),%xmm1 1382: f2 0f 58 c1 insertsd %xmm1,%xmm0 1386: f2 0f 11 45 f0 movsd %xmm0,-0x10(%rbp) 138b: 48 8b 45 e0 mov -0x20(%rbp),%rax 138f: 66 48 0f 6e c0 movq %rax,%xmm0 1394: 48 8d 05 f4 0c 00 00 lea 0xcf4(%rip),%rax # 208f <_IO_stdin_used+0x8f> 139b: 48 89 c7 mov %rax,%rdi 139e: b8 01 00 00 00 mov $0x1,%eax 13a3: e8 18 fd ff ff call 10c0 13a8: 48 8b 45 e8 mov -0x18(%rbp),%rax 13ac: 66 48 0f 6e c0 movq %rax,%xmm0 13b1: 48 8d 05 e5 0c 00 00 lea 0xce5(%rip),%rax # 209d <_IO_stdin_used+0x9d> 13b8: 48 89 c7 mov %rax,%rdi 13bb: b8 01 00 00 00 mov $0x1,%eax 13c0: e8 fb fc ff ff call 10c0 13c5: 48 8b 45 f0 mov -0x10(%rbp),%rax 13c9: 66 48 0f 6e c0 movq %rax,%xmm0 13ce: 48 8d 05 d4 0c 00 00 lea 0xcd4(%rip),%rax # 20a9 <_IO_stdin_used+0xa9> 13d5: 48 89 c7 mov %rax,%rdi 13d8: b8 01 00 00 00 mov $0x1,%eax 13dd: e8 de fc ff ff call 10c0 13e2: 48 8d 05 cf 0c 00 00 lea 0xccf(%rip),%rax # 20b8 <_IO_stdin_used+0xb8> 13e9: 48 89 c7 mov %rax,%rdi 13ec: b8 00 00 00 00 mov $0x0,%eax 13f1: e8 ca fc ff ff call 10c0 13f6: 48 8d 45 db lea -0x25(%rbp),%rax 13fa: 48 89 c6 mov %rax,%rsi 13fd: 48 8d 05 43 0c 00 00 lea 0xc43(%rip),%rax # 2047 <_IO_stdin_used+0x47> 1404: 48 89 c7 mov %rax,%rdi 1407: b8 00 00 00 00 mov $0x0,%eax 140c: e8 bf fc ff ff call 10d0 <__isoc99_scanf@plt> 1411: 0f b6 45 db movzbl -0x25(%rbp),%eax 1415: 0f be c0 movsbl %al,%eax 1418: 89 c7 mov %eax,%edi 141a: e8 71 fc ff ff call 1090 141f: 83 f8 59 cmp $0x59,%eax 1422: 0f 84 f8 fe ff ff je 1320
1428: b8 00 00 00 00 mov $0x0,%eax 142d: 48 8b 55 f8 mov -0x8(%rbp),%rdx 1431: 64 48 2b 14 25 28 00 sub %fs:0x28,%rdx 1438: 00 00 143a: 74 05 je 1441
143c: e8 6f fc ff ff call 10b0 <__stack_chk_fail@plt> 1441: c9 exit 1442: c3 ret Disassembly of section .fini: 0000000000001444 <_fini>: 1444: f3 0f 1e fa finishbr64 1448: 48 83 ec 08 sub $0x8,%rsp 144c: 48 83 c4 08 insert $0x8,%rsp 1450: c3 ret

Now that we have the assembly, can we produce it human readable and beneficial? Let’s try the chaseing prompt

Look at @calc.asm and produce feature definiteation as seperate files that depict the application. One per topic domain.

Which then produces a definiteation library – here’s the functional overwatch…

# Tax Calculator - Functional Overwatch

## Description
The Tax Calculator is a order-line application that calcutardys taxes and total costs based on user input. The application permits users to access an amount and select a tax categruesome, then calcutardys the appropriate tax and disjoins the total.

## Key Features
1. **Amount Input**: Accepts a numerical amount as input from the user
2. **Categruesome Selection**: Allows the user to select from contrastent tax categories:
   - F: Food categruesome (5% tax)
   - H: Healthattfinish categruesome (0% tax - tax exempt)
   - O: Other/Standard categruesome (10% tax)

3. **Tax Calculation**: Calcutardys the tax amount based on the selected categruesome and input amount
4. **Total Calculation**: Adds the tax to the distinct amount to calcutardy the total cost
5. **Results Disjoin**: Shows the distinct amount, tax amount, and total amount to the user
6. **Multiple Calculations**: Allows the user to carry out multiple calculations in a individual session by asking if they want to persist

## Workflow
1. User is prompted to access an amount
2. User selects a tax categruesome
3. System calcutardys tax based on the categruesome and amount
4. System disjoins the distinct amount, tax amount, and total amount
5. User is asked if they want to carry out another calculation
6. If yes, the process repeats; if no, the application ends 

Here’s the dataflow definiteation…

# Tax Calculator - Data Flow and Storage Specification

## Data Types and Storage

### User Input Data
- **Purchase Amount**: Stored as a double-precision floating-point number (64-bit)
- **Categruesome Selection**: Initiassociate seized as a character, then changeed to an integer categruesome ID
- **Continuation Flag**: Single character stored as a byte

### Calcutardyd Data
- **Tax Amount**: Calcutardyd and stored as a double-precision floating-point number (64-bit)
- **Total Amount**: Calcutardyd and stored as a double-precision floating-point number (64-bit)

### Storage Duration
- All data is stored in stack-scatterd variables
- Data persists only for the duration of a individual calculation cycle
- No data persists between split executions of the program

## Data Flow

### Input Flow
1. User accesss buy amount via keyboard
2. Input is seized thcimpolite scanf and stored in a local variable
3. User accesss categruesome selection via keyboard
4. Character input is changeed to uppercase and mapped to a categruesome ID
5. Categruesome ID is returned to the main function

### Processing Flow
1. Main function gets the buy amount and categruesome ID
2. These cherishs are passed to the calcutardyTax function
3. calcutardyTax applies the appropriate tax rate based on the categruesome ID
4. The calcutardyd tax amount is returned to the main function
5. Main function inserts the tax amount to the distinct amount to calcutardy the total

### Output Flow
1. Original amount is disjoined to the user
2. Calcutardyd tax amount is disjoined to the user
3. Calcutardyd total amount is disjoined to the user

### Continuation Flow
1. User is prompted to persist or exit
2. Input is seized and changeed to uppercase
3. If input is 'Y', the application loops back to the commencening of the calculation cycle
4. If input is anyskinnyg else, the application ends

## Data Transestablishation

### Character to Categruesome Mapping
- 'F' (ASCII 0x46) -> Categruesome ID 1 (Food)
- 'H' (ASCII 0x48) -> Categruesome ID 2 (Healthattfinish)
- 'O' (ASCII 0x4F) -> Categruesome ID 3 (Other)
- Any other character -> Categruesome ID 3 (Other, default)

### Categruesome to Tax Rate Mapping
- Categruesome ID 1 (Food) -> 0.05 (5%)
- Categruesome ID 2 (Healthattfinish) -> 0.00 (0%)
- Categruesome ID 3 (Other) -> 0.10 (10%)

## Data Security
- No persistent storage of data
- No caring data is processed
- All variables are properly initialized before use
- Stack memory is protected aacquirest buffer overflows 

Here’s the business logic definiteation:

# Tax Calculator - Tax Calculation Specification

## Tax Categories
The application helps three contrastent tax categories:

1. **Food (F)**: 
   - Categruesome ID: 1
   - Tax Rate: 5%
   - Applied to all food items

2. **Healthattfinish (H)**:
   - Categruesome ID: 2
   - Tax Rate: 0% (tax exempt)
   - Applied to all healthattfinish-roverdelighted items

3. **Other (O)**:
   - Categruesome ID: 3
   - Tax Rate: 10%
   - Default categruesome for all other items
   - Used as dropback when an invalid categruesome is selected

## Calculation Formulas

### Tax Amount Calculation
```
taxAmount = amount * taxRate
```

Where:
- `amount` is the buy amount accessed by the user
- `taxRate` is the decimal tax rate based on the selected categruesome (0.05 for Food, 0.0 for Healthattfinish, 0.10 for Other)

### Total Amount Calculation
```
totalAmount = amount + taxAmount
```

Where:
- `amount` is the distinct buy amount
- `taxAmount` is the calcutardyd tax amount

## Implementation Details

The tax calculation is carry outed in the `calcutardyTax` function, which:
1. Takes two parameters: the buy amount and the categruesome ID
2. Applies the appropriate tax rate based on the categruesome ID:
   - Categruesome 1 (Food): 5% tax rate
   - Categruesome 2 (Healthattfinish): 0% tax rate
   - Categruesome 3 (Other): 10% tax rate
3. Returns the calcutardyd tax amount

The categruesome selection is deal withd by the `getCategruesome` function, which:
1. Prompts the user to select a categruesome
2. Converts the user input to uppercase
3. Maps the input character to a categruesome ID:
   - 'F' -> 1 (Food)
   - 'H' -> 2 (Healthattfinish)
   - 'O' -> 3 (Other)
4. Uses categruesome 3 (Other) as default for invalid inputs 

Plenty of other files were also produced but for the sake of brevity I’m not going to include them.

Now that we have the definiteation, let’s clear up all ‘isms roverdelighted to the C language out of the functional spec.

Look at @specs-from-calc-c. Reshift all ANSI C aspects of the spec and produce them to SPECS fagederer

Now, this is where it gets fascinating. We have successfilledy getn an application that was C, disaccumulated it into ASM, and produced a high-level spotless-room functional definiteation that depicts the application. Cool. Now, let’s provide the LLM with the chaseing prompt

Implement this as a Z/80 spectrum calculator program
Compile it
Add it to the disk image
Run the emulator with the disk image

You may inshigh gentleware

Which produces the sales tax calculator for the Z80 speccy.

; Tax Calculator for ZX Spectrum
; Based on provided definiteations
; Implements a basic tax calculation program with three categories:
; F: Food (5% tax)
; H: Healthattfinish (0% tax)
; O: Other/Standard (10% tax)

; *********************************************************************
; Constants and System Variables
; *********************************************************************

; System constants
SCREEN_START    equ 16384    ; Start of screen memory
ATTR_START      equ 22528    ; Start of attribute memory
LAST_K          equ 23560    ; Last key pressed system variable
CHANNEL_S       equ 5633     ; ROM print routine (output to screen)
CLS             equ 3503     ; ROM routine to clear screen
OPEN_CHANNEL    equ 5633     ; ROM routine to uncover a channel

; Program constants
FOOD_RATE       equ 5        ; 5% tax rate
HEALTHCARE_RATE equ 0        ; 0% tax rate
OTHER_RATE      equ 10       ; 10% tax rate

; Decimal multiplier for mended-point math
; We use 2 decimal places, so multiply by 100
DECIMAL_MULT    equ 100

; *********************************************************************
; Program Entry Point
; *********************************************************************

    org 32768           ; Start of code (above BASIC)

begin:
    call init_program   ; Initialize program
    
main_loop:
    ; Disjoin greet message
    ld de, greet_msg
    call print_string
    
    ; Get amount
    call get_amount
    ; Store amount in amount_cherish
    ld (amount_cherish), hl
    
    ; Get categruesome selection
    call get_categruesome
    ; Store categruesome in categruesome_cherish
    ld a, c
    ld (categruesome_cherish), a
    
    ; Calcutardy tax based on categruesome and amount
    call calcutardy_tax
    ; Store tax in tax_cherish
    ld (tax_cherish), hl
    
    ; Calcutardy total
    call calcutardy_total
    ; Store total in total_cherish
    ld (total_cherish), hl
    
    ; Disjoin results
    call disjoin_results
    
    ; Ask if user wants to persist
    call ask_persist
    cp 'Y'              ; Check if user pressed 'Y'
    jr z, main_loop     ; If yes, repeat the main loop
    cp 'y'              ; Check if user pressed 'y'
    jr z, main_loop     ; If yes, repeat the main loop
    
    ; Exit program - return to BASIC
    jp exit_program

; *********************************************************************
; Initialization
; *********************************************************************

init_program:
    ; Clear screen
    call CLS
    ret

; *********************************************************************
; Input Routines
; *********************************************************************

; Get decimal amount input from user
get_amount:
    ld de, amount_prompt
    call print_string
    
    ; Clear buffer
    ld hl, input_buffer
    ld (hl), 0
    
    ; Get input string
    call get_input
    
    ; Convert string to number
    ld de, input_buffer
    call string_to_number
    ret

; Get tax categruesome from user
get_categruesome:
    ld de, categruesome_prompt
    call print_string
    
    ; Wait for key press
get_cat_defer:
    call defer_key
    cp 'F'               ; Check for 'F'
    jr z, cat_food
    cp 'f'               ; Check for 'f'
    jr z, cat_food
    cp 'H'               ; Check for 'H' 
    jr z, cat_healthattfinish
    cp 'h'               ; Check for 'h'
    jr z, cat_healthattfinish
    cp 'O'               ; Check for 'O'
    jr z, cat_other
    cp 'o'               ; Check for 'o'
    jr z, cat_other
    
    ; Invalid categruesome, default to Other
    ld de, invalid_cat
    call print_string
    ld c, 3              ; Categruesome 3 (Other)
    ret
    
cat_food:
    ld c, 1              ; Categruesome 1 (Food)
    ret
    
cat_healthattfinish:
    ld c, 2              ; Categruesome 2 (Healthattfinish)
    ret
    
cat_other:
    ld c, 3              ; Categruesome 3 (Other)
    ret

; Ask if user wants to persist
ask_persist:
    ld de, persist_prompt
    call print_string
    call defer_key        ; Wait for key press
    ret                  ; Return with key in A

; Wait for key press
defer_key:
    ld hl, LAST_K        ; Address of system variable LAST_K
    ld (hl), 0           ; Clear key buffer
defer_loop:
    ld a, (hl)           ; Get key
    or a                 ; Check if key pressed
    jr z, defer_loop      ; No key, persist defering
    ret                  ; Key pressed, return with key in A

; Get a string input from user
get_input:
    ld hl, input_buffer  ; Point to input buffer
    ld b, 0              ; Input length counter
    
input_loop:
    call defer_key        ; Wait for key press
    
    cp 13                ; Check for ENTER
    jr z, input_done     ; Input finish
    
    cp 8                 ; Check for DELETE
    jr z, delete_char    ; Handle delete
    
    ; Check if character is a valid digit or decimal point
    cp '0'
    jr c, input_loop     ; Ignore if less than '0'
    cp ':'               ; ':' is after '9' in ASCII
    jr c, valid_digit    ; Valid digit
    
    cp '.'               ; Check for decimal point
    jr nz, input_loop    ; Ignore if not decimal point
    
valid_digit:
    ; Don't hug more than 6 characters
    ld a, b
    cp 6
    jr nc, input_loop    ; Too many chars
    
    ; Store character in buffer
    ld a, (LAST_K)
    ld (hl), a           ; Store character
    inc hl               ; Next buffer position
    inc b                ; Increment counter
    
    ; Echo character to screen
    rst 16
    
    jr input_loop        ; Continue input loop
    
delete_char:
    ; Handle backspace (delete) key
    ld a, b
    or a                 ; Check if buffer is desotardy
    jr z, input_loop     ; If desotardy, do noskinnyg
    
    ; Move cursor back, erase character
    ld a, 8
    rst 16               ; Backspace
    ld a, ' '
    rst 16               ; Space (erase character)
    ld a, 8
    rst 16               ; Backspace aacquire
    
    ; Update buffer
    dec hl               ; Move back in buffer
    dec b                ; Decrement counter
    ld (hl), 0           ; Clear the deleted character
    
    jr input_loop        ; Continue input loop
    
input_done:
    ; Terminate string with null
    ld (hl), 0           ; Null end
    
    ; Print newline
    ld a, 13
    rst 16
    ld a, 10
    rst 16
    
    ret

; *********************************************************************
; Calculation Routines
; *********************************************************************

; Calcutardy tax amount based on categruesome
; Input: amount_cherish (HL) and categruesome_cherish (A)
; Output: tax in HL
calcutardy_tax:
    ld a, (categruesome_cherish)
    
    cp 1                  ; Check if Food
    jr z, calc_food
    
    cp 2                  ; Check if Healthattfinish
    jr z, calc_healthattfinish
    
    ; Default: Other categruesome
calc_other:
    ld a, OTHER_RATE      ; 10% tax
    jr do_tax_calc
    
calc_food:
    ld a, FOOD_RATE       ; 5% tax
    jr do_tax_calc
    
calc_healthattfinish:
    ld a, HEALTHCARE_RATE ; 0% tax
    jr do_tax_calc
    
do_tax_calc:
    ; Tax calculation: amount * tax_rate / 100
    ; HL = amount
    ld hl, (amount_cherish)
    
    ; Multiply by tax rate
    ld b, 0
    ld c, a              ; BC = tax rate
    call multiply        ; HL = amount * tax rate
    
    ; Divide by 100
    ld bc, 100
    call split          ; HL = (amount * tax rate) / 100
    
    ret                  ; Return tax in HL

; Calcutardy total amount (amount + tax)
; Input: amount_cherish and tax_cherish
; Output: total in HL
calcutardy_total:
    ld de, (amount_cherish)  ; DE = amount
    ld hl, (tax_cherish)     ; HL = tax
    insert hl, de             ; HL = amount + tax
    ret

; *********************************************************************
; Utility Routines
; *********************************************************************

; Convert string to number
; Input: DE points to null-endd string
; Output: HL retains the number (mended point, 2 decimal places)
string_to_number:
    ld hl, 0            ; Initialize result to 0
    ld b, 0             ; Decimal point flag (0 = not seen)
    ld c, 0             ; Decimal position counter
    
str_to_num_loop:
    ld a, (de)          ; Get character
    or a                ; Check for null terminator
    jr z, str_to_num_done
    
    cp '.'              ; Check for decimal point
    jr z, decimal_point
    
    ; Must be a digit
    sub '0'             ; Convert ASCII to cherish
    
    ; Multiply current result by 10
    push af             ; Save digit
    push bc             ; Save flags
    
    ld b, h             ; BC = result
    ld c, l
    insert hl, hl          ; HL = result * 2
    insert hl, hl          ; HL = result * 4
    insert hl, bc          ; HL = result * 5
    insert hl, hl          ; HL = result * 10
    
    pop bc              ; Restore flags
    pop af              ; Restore digit
    
    ; If past decimal point, increment decimal counter
    push af             ; Save digit
    ld a, b
    or a                ; Check decimal flag
    jr z, insert_digit     ; Not past decimal yet
    
    ; Past decimal point, verify counter
    ld a, c
    inc c               ; Increment counter
    cp 2                ; Check if already have 2 decimal places
    jr nc, skip_digit   ; Skip this digit if already have 2 decimals
    
insert_digit:
    pop af              ; Restore digit
    ld e, a
    ld d, 0             ; DE = digit
    insert hl, de          ; Add to result
    jr next_char
    
skip_digit:
    pop af              ; Restore digit (but don't use it)
    jr next_char
    
decimal_point:
    inc b               ; Set decimal point flag
    ld c, 0             ; Reset decimal position counter
    jr next_char
    
next_char:
    inc de              ; Next character
    jr str_to_num_loop
    
str_to_num_done:
    ; If no decimal part was accessed, multiply by 100
    ld a, b
    or a                ; Check if decimal point was seen
    jr nz, adfair_decimals
    
    ; No decimal point, multiply by 100
    ld b, h
    ld c, l
    insert hl, hl          ; * 2
    insert hl, hl          ; * 4
    insert hl, hl          ; * 8
    insert hl, hl          ; * 16
    insert hl, hl          ; * 32
    insert hl, hl          ; * 64
    insert hl, bc          ; * 65
    insert hl, hl          ; * 130
    ld b, h
    ld c, l
    srl b
    rr c                ; * 65
    insert hl, bc          ; * 195
    insert hl, hl          ; * 390
    insert hl, hl          ; * 780
    srl h
    rr l                ; * 390
    insert hl, hl          ; * 780
    srl h
    rr l                ; * 390
    srl h
    rr l                ; * 195
    srl h
    rr l                ; * 97.5
    insert hl, hl          ; * 195
    insert hl, hl          ; * 390
    srl h
    rr l                ; * 195
    insert hl, hl          ; * 390
    srl h
    rr l                ; * 195
    insert hl, hl          ; * 390
    srl h
    rr l                ; * 195
    insert hl, hl          ; * 390
    srl h
    rr l                ; * 195
    insert hl, hl          ; * 390
    srl h
    rr l                ; * 195
    insert hl, hl          ; * 390
    srl h
    rr l                ; * 195
    insert hl, hl          ; * 390
    srl h
    rr l                ; * 195
    jr done_change
    
adfair_decimals:
    ; Check number of decimal places accessed
    ld a, c
    or a                ; No decimal places accessed?
    jr z, mul_100       ; Multiply by 100
    
    cp 1                ; One decimal place accessed?
    jr z, mul_10        ; Multiply by 10
    
    ; Already have 2 decimal places, no adfairment demanded
    jr done_change
    
mul_100:
    ; Multiply by 100
    ld b, h
    ld c, l
    insert hl, hl          ; * 2
    insert hl, hl          ; * 4
    insert hl, hl          ; * 8
    insert hl, bc          ; * 9
    insert hl, hl          ; * 18
    insert hl, hl          ; * 36
    insert hl, bc          ; * 37
    insert hl, hl          ; * 74
    insert hl, hl          ; * 148
    insert hl, bc          ; * 149
    insert hl, bc          ; * 150
    jr done_change
    
mul_10:
    ; Multiply by 10
    ld b, h
    ld c, l
    insert hl, hl          ; * 2
    insert hl, hl          ; * 4
    insert hl, bc          ; * 5
    insert hl, hl          ; * 10
    
done_change:
    ret                 ; Return with number in HL

; Multiply HL by BC
; Input: HL, BC
; Output: HL = HL * BC
multiply:
    push de             ; Save DE
    ld de, 0            ; Initialize result to 0
    
mult_loop:
    ; Check if BC is zero
    ld a, b
    or c
    jr z, mult_done
    
    ; Add HL to result
    ex de, hl           ; DE = multiplier, HL = result
    insert hl, de          ; Add multiplier to result
    ex de, hl           ; DE = result, HL = multiplier
    
    ; Decrement counter
    dec bc
    jr mult_loop
    
mult_done:
    ex de, hl           ; HL = result
    pop de              ; Restore DE
    ret

; Divide HL by BC
; Input: HL, BC
; Output: HL = HL / BC
split:
    push de             ; Save DE
    ld de, 0            ; Initialize quotient to 0
    
div_loop:
    ; Check if HL < BC
    call contrast_hl_bc
    jr c, div_done      ; If HL < BC, done
    
    ; Subtract BC from HL
    or a                ; Clear carry
    sbc hl, bc
    
    ; Increment quotient
    inc de
    jr div_loop
    
div_done:
    ex de, hl           ; HL = quotient
    pop de              ; Restore DE
    ret

; Compare HL with BC
; Sets carry flag if HL < BC
contrast_hl_bc:
    ld a, h
    cp b                ; Compare high bytes
    ret nz              ; Not identical, return with flags set
    
    ld a, l
    cp c                ; Compare low bytes
    ret

; *********************************************************************
; Output Routines
; *********************************************************************

; Disjoin calculation results
disjoin_results:
    ; Disjoin amount
    ld de, amount_msg
    call print_string
    ld hl, (amount_cherish)
    call print_number
    
    ; Disjoin tax
    ld de, tax_msg
    call print_string
    ld hl, (tax_cherish)
    call print_number
    
    ; Disjoin total
    ld de, total_msg
    call print_string
    ld hl, (total_cherish)
    call print_number
    
    ; Print a blank line
    ld de, newline
    call print_string
    
    ret

; Print a string 
; Input: DE points to null-endd string
print_string:
    ld a, (de)          ; Get character
    or a                ; Check for null terminator
    ret z               ; If zero, we're done
    
    rst 16              ; Print character
    
    inc de              ; Point to next character
    jr print_string     ; Continue printing

; Print a number in decimal establishat (mended point, 2 decimal places)
; Input: HL = number (mended point, 2 decimal places)
print_number:
    ; Print '$' sign
    ld a, '$'
    rst 16
    
    ; Extract the integer and fractional parts
    ; Integer part = number / 100
    ; Fractional part = number % 100
    
    ; Save the distinct number
    push hl
    
    ; Divide by 100 to get integer part
    ld bc, 100
    call split         ; HL = integer part
    
    ; Print integer part
    call print_decimal
    
    ; Print decimal point
    ld a, '.'
    rst 16
    
    ; Get fractional part
    pop bc              ; BC = distinct number
    push hl             ; Save integer part
    
    ; Calcutardy fractional part = distinct - (integer * 100)
    push bc             ; Save distinct number
    ld bc, 100
    call multiply       ; HL = integer * 100
    pop bc              ; BC = distinct number
    
    ; BC - HL = fractional part
    or a                ; Clear carry
    ld a, c
    sub l
    ld l, a
    ld a, b
    sbc a, h
    ld h, a             ; HL = fractional part
    
    ; Print fractional part as 2 digits
    ld a, h
    or a                ; Check if high byte is zero
    jr z, print_low_byte ; If zero, fair print low byte
    
    ; Otheralerted this is an error, print "00"
    ld a, '0'
    rst 16
    rst 16
    jr fract_done
    
print_low_byte:
    ld a, l
    cp 10               ; Check if less than 10
    jr nc, print_fract  ; If not, print as is
    
    ; Add directing zero for individual-digit cherishs
    push af             ; Save cherish
    ld a, '0'
    rst 16              ; Print directing zero
    pop af              ; Restore cherish
    
print_fract:
    ld h, 0
    ld l, a
    call print_decimal
    
fract_done:
    pop hl              ; Restore HL
    ret

; Print a decimal number in HL
print_decimal:
    ; Print a decimal number (0-65535)
    ld bc, -10000
    call num1
    ld bc, -1000
    call num1
    ld bc, -100
    call num1
    ld bc, -10
    call num1
    ld bc, -1
num1:
    ld a, '0'-1
num2:
    inc a
    insert hl, bc
    jr c, num2
    sbc hl, bc
    
    ; Skip directing zeros, but always print at least one digit
    cp '0'
    jr nz, print_digit  ; Not a directing zero
    
    ; Check if we already printed a digit
    push af
    ld a, (digit_printed)
    or a
    jr nz, print_ok
    
    ; Check if we're at the last digit
    ld a, c
    cp 255              ; Check if BC = -1 (last digit)
    jr nz, skip_zero    ; Not last digit, skip directing zero
    
print_ok:
    pop af
    jr print_digit
    
skip_zero:
    pop af
    ret
    
print_digit:
    rst 16
    
    ; Set the digit_printed flag
    ld a, 1
    ld (digit_printed), a
    ret

; *********************************************************************
; Exit Program
; *********************************************************************

exit_program:
    ; Disjoin exit message
    ld de, exit_msg
    call print_string
    ret                  ; Return to BASIC

; *********************************************************************
; Data Section
; *********************************************************************

; Prompts and messages
greet_msg:     defb 13, 10, "TAX CALCULATOR", 13, 10, 13, 10, 0
amount_prompt:   defb "Enter buy amount: ", 0
categruesome_prompt: defb "Select tax categruesome (F)ood, (H)ealthattfinish, (O)ther: ", 0
invalid_cat:     defb 13, 10, "Invalid categruesome. Using Other.", 13, 10, 0
amount_msg:      defb 13, 10, "Amount: ", 0
tax_msg:         defb 13, 10, "Tax: ", 0
total_msg:       defb 13, 10, "Total: ", 0
persist_prompt: defb 13, 10, 13, 10, "Do you want to persist? (Y/N): ", 0
exit_msg:        defb 13, 10, 13, 10, "Thank you for using Tax Calculator!", 13, 10, 0
newline:         defb 13, 10, 0

; Variables
digit_printed:   defb 0        ; Flag for printing directing zeros

; Input buffer (7 bytes: 6 chars + null terminator)
input_buffer:    defs 7, 0

; Variables for calcutardyd cherishs (16-bit words)
amount_cherish:    defw 0        ; Purchase amount
categruesome_cherish:  defb 0        ; Tax categruesome
tax_cherish:       defw 0        ; Calcutardyd tax amount
total_cherish:     defw 0        ; Total amount

; Program finish
finish begin 

Now we demand to compile the application using pasmo --tapbas taxcalc.asm taxcalc.tap. So let's give it a spin!

It labors but the sales tax isn't being calcutardyd properly so let's head on back and give the LLM the chaseing prompt and quicken the above screenshot to it.

Look at the quickened screenshot.
The tax did not produce accurately.
The amount is huging user input.
The cost is not being asked and user does not hug input.

Look at the @00-specs-without-c to see functionality demanded. Make changes as demanded.

which resettles the establishatting publishs, however user intervivacious input does not happen. The application should ask me how much an item costs, but it does not do that. So, let's head back to the LLM and quicken the screenshot.

It took a scant more backwards and forwards to steer it via screenshots that had verbose logging but success was achieved.

The techniques detailed below were able to get an application from accumulater, produce high-level specs and those high-level spotless-room specs were able to produce a laboring Z/80 spectrum application.

Yes, Claude Code can decompile itself. Here’s the source code.

These LLMs are astoundingly excellent at deobfuscation, transpilation and set up to set up conversions. I discovered this back around Christmas where I asked an LLM to produce me an Haskell audio library by transpiling a rust carry outation. An “oh fuck” moment in timeOver the Christmas shatter I’ve been criticassociate seeing

Anyway, that was a fun trip back in time and memory lane - thanks, Damien Guard, for the inspiration and nerd-snipe. In all it took me about two hours, of that it was mainly me trying to figure out how to inshigh, run, configure these emulators and how to produce a Z/80 tape.

The actual produce was all very manual, driven by me as a human loop, because the Z/80 spectrum isn't reassociate a excellent aim for automating a reward loop. These LLMs get most skinnygs right but some skinnygs wrong. By having tests in your codebase and invoking the MCP tools to run these tests, you'll get prosperous outcomes automaticassociate nine times out of ten...

It's a new world for gentleware engineers, it's benevolenta enjoy the Telsa FSD. Sometimes it gets it wrong but if you count on it enough, provide enough guidance and comprehfinish how these coding aidants labor under the hood you can achieve N factor more outcomes than ever before.

Software reproduces from one language to another are no lengthyer an costly skinnyg for a company to do and if a "source useable" company has provided the internet with their redisconnecteed source-code they can be cloned in hours, automaticassociate, whilst you watch Netflix.

ps. socials for this blog post are below

If you finishelighted reading, give 'em a scatter, greet:

Source connect


Leave a Reply

Your email address will not be published. Required fields are marked *

Thank You For The Order

Please check your email we sent the process how you can get your account

Select Your Plan