Hacker News new | ask | show | jobs
by userbinator 3882 days ago
You may "How to blink a light extremely inefficiently 10 different ways." ;-)

Seriously, not even one Asm example? If you have a PC that has a parallel port and can boot to DOS, you can stick a LED in series with a 100-ohm resistor across pins 2(+) and 18(-) and do this:

        mov dx, 378h
        xor ax, ax
    blinkloop:
        out dx, al
        mov cx, 36
        call delay
        not ax
        jmp blinkloop

    delay:
        hlt
        loop delay
        ret
I find it somewhat amazing that this program, in Assembly, is actually shorter than the 10 HLL programs in the article.
3 comments

Here's something more appropriate (air coded, modulo my iPhone's spell corrector)

  section .text
  global _start

  _start:

  ; Write the ‘1’ to a file
  mov eax, 4       ; sys_write
  mov edx, 1       ; # of bytes to write
  mov ecx, ‘1’     ; Means light should be on
  mov ebx, file_open ; File descriptor
  mov eax, 4       ; Call to sys_write 
  int 0x80         ; Call kernel to write file
  
  ; Close file
  move eax, 6
  mov mov ebx, 
  int 0x80         ; Call kernel to close file
  
  ; Quit to OS
  move eax, 1      ; SYS_EXIT
  int 0x80         ; Call kernel to exit to OS
  
  section.data
  
  filename db ‘/sys/class/leds/beaglebone:green:usr0/brightness’,0
  len equ $-filename

  section .bss
  file_open resb 1
  state db ‘1’
That's not a fair comparison in any way. Your assembler program doesn't do half of the original code.
That's the point. It doesn't do all the work of the original code because it doesn't need to. You don't need a whole OS and several layers of abstraction just to blink an LED, not even a dozen instructions (and I notice now, since I was writing it off the top of my head, that the delay subroutine is only called once, so there's another two "wasted" instructions...)

I think it's very important that programmers are exposed to such "absolute minimum simplicity" solutions, as it helps greatly with understanding the essence of the problem and its solution - in this case it's nothing more than toggling a bit in an I/O port. Complexity can be added afterwards as needed, but not gratuitously.

I like how one of the other comments here and in the article mentions that there's no error handling in many of the examples, since it brings up another point about complexity: it can introduce opportunities for errors. If you're working with the GPIO directly, errors either can't occur, or they're hardware-level (e.g. shorted output) and nothing can really be done about it anyway unless the hardware has additional features for signaling such conditions. If you're going through the OS' filesystem, errors can occur at any one of the multiple layers for not-so-related reasons to the actual task. One should then ask the question of whether the code that's added to handle errors is actually doing something useful for the task, or serves no purpose beyond satisfying the other layers of complexity that introduce them.

Good points, and I agree about understanding minimal simplicity and you don't need an OS and several layers of abstractions to blink a light. The post wasn't explicit (I think it is now after updating), but the intent was to demonstrate the variety of languages available on Linux based platforms that have GPIO SysFS, so assembly was never considered. It is more focused on those environments in which these HLL do have a role/place.
userbinator's example does not conform to the API, which writes to a file (and on some platforms, uses best practices to write atomically and check for errors to boot). I took a stab at it elsewhere.