Guest User

James Block

a guest
Apr 12th, 2009
179
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. ; for NASM, a 386 or better, and a 2.6-series Linux kernel
  2. ; it should run fine on a 64-bit system with appropriate flags for NASM
  3. ; assemble with nasm -f elf FILENAME.asm && ld FILENAME.o -o OUTPUTFILENAME
  4. ; run as ./OUTPUTFILENAME < INPUT_NUMBERS.txt
  5. ; expect weirdness with nonconforming input. this is pure assembly, you know
  6. ; each input number should be at most 32 bits, and the sum at most 64 bits
  7.  
  8. buffersize equ (1<<16)  ;use 64kB chunks; can be set to any value
  9.             ;64kB is fastest on this old Willamette P4
  10.  
  11. section .data
  12.     message: db "Grand total:"
  13.     printbuffer: times 23 db 0x20
  14.     dw 0x0A
  15.     msglen equ $ - message
  16.  
  17. section .text
  18.     global _start
  19.  
  20. _start:
  21.     ;we want to read a bunch of numbers from STDIN
  22.     ;we'll do this by allocating memory with mmap()
  23.     ;and then reading stdin with read()
  24.     ;
  25.     ;mmap signature:
  26.     ; void* mmap(void* start, size_t length, int prot, int flags,
  27.     ;   int fd, off_t offset);
  28.     ; (defined in <sys/mman.h>)
  29.     ;
  30.     ;arguments:
  31.     ; start - pass 0, usually ignored
  32.     ; length - pass $BIGNUM to allocate a $BIGNUM chunk
  33.     ; prot - pass PROT_READ | PROT_WRITE (0x01|0x02)
  34.     ; flags - pass MAP_PRIVATE (0x02) | MAP_ANONYMOUS (0x20)
  35.     ; fd - pass anything (-1)
  36.     ; offset - pass anything
  37.     ;
  38.     ; linux calling convention: 6-arg syscalls use the stack
  39.     ;   push arguments in REVERSE order
  40.     ;
  41.     ; system call number goes in eax:
  42.     ;  exit:    1
  43.     ;  read:    3
  44.     ;  write:   4
  45.     ;  mmap:    90
  46.     ;  munmap:  91
  47.  
  48.     mov esi, buffersize ;store buffer size in esi
  49.  
  50.     push dword 0    ;offset
  51.     push dword -1   ;fd
  52.     push dword 0x22 ;flags - MAP_PRIVATE|MAP_ANONYMOUS
  53.     push dword 0x03 ;prot - PROT_READ|PROT_WRITE
  54.     push dword esi  ;allocation size
  55.     push dword 0    ;start
  56.     mov eax, 90
  57.     mov ebx, esp
  58.    
  59.     int 80h
  60.     add esp, (4*6)  ;clean up the refuse from calling mmap()
  61.    
  62.     ;now eax holds the start address for our memory! yay!
  63.     ;let's put it in ebp instead, since ebp isn't good for much else
  64.     mov ebp, eax
  65.    
  66.     ;now let's read() in the data from stdin
  67.     ;read() signature:
  68.     ; ssize_t read(int fd, void* buf, size_t count)
  69.     ;3-arg syscalls pass arguments in registers, so
  70.     ;this one's much easier than mmap():
  71.    
  72.     mov ecx, eax
  73.     mov ebx, 0
  74.     mov eax, 3
  75.     mov edx, esi
  76.     int 80h
  77.    
  78.     ;accumulate in the traditional pairing edx:eax
  79.     ;let ecx index our position in the memory block
  80.    
  81.     ;read digits into ebx, accumulate into numbers in edi
  82.     ; then sum edi to the main accumulator, edx:eax
  83.     ; anything but a digit ends a number
  84.     ; zero byte ends all counting
  85.  
  86.     xor edx, edx
  87.     xor eax, eax
  88.     xor ecx, ecx
  89.     dec ecx
  90.  
  91. readdigit:
  92.     xor edi, edi
  93. readdigit_lp:
  94.     xor ebx, ebx
  95.     inc ecx
  96.     cmp ecx, esi
  97.     je readmore
  98. gotmore:mov bl, byte [ebp+ecx]
  99.     test bl, bl
  100.     jz finished_summing     ;exit on zero byte
  101.    
  102.     sub bl, 48
  103.     js next_number
  104.     cmp bl, 9
  105.     ja next_number  ;if this is not a digit, skip it and sum
  106.  
  107.     shl edi, 1
  108.     lea edi, [edi*4 + edi]
  109.     add edi, ebx
  110.     jmp readdigit_lp
  111.    
  112. next_number:
  113.     add eax, edi
  114.     jnc readdigit
  115.     inc edx
  116.     jmp readdigit
  117.  
  118. readmore:
  119.     mov esp, eax
  120.     mov eax, 3
  121.     xor ebx, ebx
  122.     mov ecx, ebp
  123.     xchg edx, esi
  124.     int 80h
  125.    
  126.     ;if we didn't fill the whole buffer, stick a zero byte after the
  127.     ; bit we *did* read, to ensure proper termination of the loop
  128.    
  129.     cmp eax, edx
  130.     je readcleanup
  131.     mov byte [ebp+eax+1], 00
  132. readcleanup:
  133.     xor ecx, ecx
  134.     xchg edx, esi
  135.     mov eax, esp
  136.     jmp gotmore
  137.  
  138.  
  139. finished_summing:
  140.     ;edx:eax contains the 64-bit sum
  141.     ;now we have to print it
  142.     ;the following is an EXTREMELY ugly printf(%llu) substitute
  143.  
  144.     mov ecx, (printbuffer+22)
  145.     mov ebp, 10
  146.     mov esp, 429496729
  147.    
  148. printlp64:
  149.     ;if we can bail on this horrid 64-bit print loop
  150.     ; and use a much saner 32-bit version,
  151.     ; then, damn it, EXIT NOW
  152.     test edx, edx
  153.     jz printlp32
  154.  
  155.     ;algorithm (64-bit divmod): let W = 2**32, Z = X + Y*W
  156.     ; (i.e., X is eax and Y is edx)
  157.     ; then let M = 10 (modulus) and define
  158.     ; X divmod M = (x_D, x_M)   (the definition of divmod:
  159.     ; Y divmod M = (y_D, y_M)   (quotient, remainder))
  160.     ; W divmod M = (W_D, W_M)
  161.     ;
  162.     ; let u = x_M + y_M * W_M and calculate
  163.     ; u divmod M = (u_D, u_M)
  164.     ;
  165.     ; then the following is true:
  166.     ; Z divmod M = (y_D * W + x_D + y_M*W_D + u_D, u_M)
  167.     ;
  168.     ; the following pile of junk implements the above
  169.     ;  (and allows for overflow in a couple places)
  170.  
  171.     mov edi, eax
  172.     mov eax, edx
  173.     xor edx, edx
  174.     div ebp
  175.     lea ebx, [edx*3]
  176.     shl ebx, 1
  177.     mov esi, eax
  178.     mov eax, edx
  179.     mul esp
  180.     ;edx:eax has y_M*W_D, ebx has y_M*W_M, edi has x, esi has y_D
  181.     add esi, edx
  182.     xor edx, edx
  183.     xchg eax, edi
  184.     div ebp
  185.     ;eax has x_D, edx has x_M, esi has y_D, edi has y_M*W_D
  186.     add ebx, edx    ;ebx has u
  187.     add edi, eax
  188.     xor edx, edx
  189.     mov eax, ebx
  190.     div ebp
  191.     ;eax has u_D, edx has u_M
  192.     add dl, 0x30
  193.     mov byte [ecx], dl
  194.     dec ecx
  195.     mov edx, esi
  196.     add eax, edi
  197.     jnc printlp64
  198.     inc edx
  199.     jmp printlp64
  200.    
  201. printlp32:
  202.     div ebp
  203.     add dl, 0x30
  204.     mov byte [ecx], dl
  205.     dec ecx
  206.     xor edx, edx
  207.     test eax, eax
  208.     jnz printlp32
  209.  
  210.  
  211. EXIT:
  212.     mov eax, 4
  213.     mov ebx, 1
  214.     mov ecx, message
  215.     mov edx, msglen
  216.     int 80h
  217.  
  218.     mov eax, 1
  219.     mov ebx, 0
  220.     int 80h
  221.  
  222.  
Advertisement
Add Comment
Please, Sign In to add comment