-1

Before I learn a bit of Assembly had heard that you had to "program directly in hardware", "I had to do everything from scratch." For example to write a character without an operating system I thought I would have to know how my monitor work and write pixel by pixel of the character.

So I got interested and I learn a little. And I saw it was not so "close to the metal". Then wanted someone to explain to me how this works and if it is possible to go deeper and really control all hardware.

Here is a code that prints a character:

[BITS 16]
[ORG 0x7C00]

MOV AL, 65
CALL PrintCharacter
JMP $

PrintCharacter:

MOV AH, 0x0E
MOV BH, 0x00
MOV BL, 0x07

INT 0x10
RET

TIMES 510 - ($ - $$) db 0
DW 0xAA55
dromenox
  • 19
  • 1
  • 2
    This code makes use of BIOS services via interrupt 0x10. As such, the code that really does the direct hardware access has been written by your BIOS provider. As this example shows, when using assembly you *don't have to program hardware directly*, you can use whatever services your environment offsers (such as BIOS interrupts or OS system calls). – Jester Oct 20 '14 at 11:56
  • Using DOSBOX perhaps, you would still like to use BIOS service 0x10 to enter VGA mode. In VGA mode 0x0D the address range from A000:0000 to A000:f9ff would contain the paletted pixel data. Or in text mode the next 2000 bytes starting from B800:0000 would allow writing an IBM ASCII character and its color code to the screen as directly as possible. – Aki Suihkonen Oct 20 '14 at 12:34
  • 1
    "Assembly" and "bare metal" programming are somewhat related, but by no means equivalent. One can code in assembly while using an operating systems and user space libraries. Conversely, much bare-metal code is not written in assembly. – EOF Oct 20 '14 at 22:40

1 Answers1

3

Lower than assembler is machine code.

However machine code instructions have an 1:1 relation to assembly instructions so there is nothing that can be done in machine code which cannot be done in assembler.

In early times of computing there were computers where you had to enter the machine code directly. The Mits Altair 680b is one of the examples for such a computer:

It had a lot of front panel switches which allowed you to modify the content of the RAM without (!) using the CPU: The CPU was stopped when the front panel switches were in use. You had to translate assembler code into binary code and load the program into the RAM this way. Then you started the CPU.

Later the KIM-1 computer (it is said to be the first affordable hobbyist computer) was released. This computer allowed entering the machine code as hexadecimal code but in contrast to the Mits computer a program running in the background (which means: the CPU) was responsible for writing the data entered by the keyboard into the RAM.

In theory it is still possible to enter Windows programs in hexadecimal code (using a hexadecimal editor) you want to. However this will bring no benefit compared to assembler code!

Martin Rosenau
  • 17,897
  • 3
  • 19
  • 38
  • But today, what I have to do to communicate directly with the hardware of my monitor for example? For I draw pixel by pixel without interruptions that do this for me? – dromenox Oct 20 '14 at 12:24
  • 2
    Fun fact: sometimes assembly is not 1:1 to machine code. On x86 for example, you can encode some instructions such as `mov eax, ebx` in two different ways to machine code. – Jester Oct 20 '14 at 13:28
  • On MIPS and on ARM in Thumb mode, assembly commands and instructions are most definitely not 1-to-1. That said, specifically for directly outputting pixels on the monitor, you use VGA hardware - registers via I/O ports and the framebuffer at A000:0000. Read up on VGA: http://www.osdever.net/FreeVGA/vga/vga.htm – Seva Alekseyev Oct 20 '14 at 14:52
  • Indeed in MIPS and ARM some assembler instructions (like "LDR =" for ARM) will produce two machine code instructions. This is however not the point. What I want to say with "1:1 relation" is that any machine instruction can be created using assembler code and machine code can be converted back to assembler code. Instructions like the "NOP" instruction on MIPS that can be represented by 100s of different machine code instructions that all behave the same way are existing. – Martin Rosenau Oct 20 '14 at 15:58
  • @dromenox: An "INT" instruction is nothing but a special "CALL" instruction. When the CPU is in so-called protected mode (Windows, Linux) you do not have direct access to the hardware; it is restricted to the operating system (which is entered using an INT instruction). In real-mode (MS-DOS) you have access to the real hardware. The code that is called by the INT instruction will write code to special memory locations (e.g. A000:0000) and perform I/O operations using the IN and OUT instructions. – Martin Rosenau Oct 20 '14 at 16:21
  • @MartinRosenau Thank you! Now it's getting clearer! But of all the graphical examples in assembly I've seen used low resolutions and few colors. How can for example draw on a 1920x1080 monitor using millions of colors available? – dromenox Oct 20 '14 at 17:38
  • @dromenox: The highest resolution that is standardized among graphics chipset manufacturers is 640x480x16; for many graphics chipsets the 800x600x16 resolution is also identical. However all higher resolutions work differently on different chipsets. This means it is not possible to write code for such resolutions that works on different graphics chipsets. Even Linux calls the "INT" code for such resolutions! – Martin Rosenau Oct 20 '14 at 17:43
  • "However machine code instructions have an 1:1 relation to assembly instructions so there is nothing that can be done in machine code which cannot be done in assembler." This is not exactly true. In x86 there are several possible encodings for the same assembly instruction. It matters if you want to write self-modifying code or overlapping instructions or if you want to edit an executable statically or dynamically, w/o source. Also, not all assemblers implement all the instructions and forms of the target machine code. In those cases machine code is the solution, eg. using `db` in the source. – nrz Oct 24 '14 at 20:15