show_string_II
In this post, you read about the reason why I decided to change the code of show_string and make a second version for it.
show_string_II kept the same core as it was in show_string but I cast it again in the new format and, very important now, I preserved the register used by the procedure itself by pushing them on the stack at the beginning of the procedure and popping them off the stack again at the end. This is a change that I realized I had to bring in my code since I had a couple of unexpected bugs because in my previous coding style the procedures weren't preserving the registers. Previously, I was writing which registers were used during the procedure, meaning that I couldn't rely on the state of such registers when the procedure returned. In simple context it was working, but as complexity rose and procedures were calling other procedures this written notification wasn't working anymore. This was not safe and I made some mistakes. So I changed strategy and I decided to preserve the registers used so that every procedure had to return in the same state as it was before the call and this kept the calling chain clean. It is disadvantageous to push and pop values on the stack because it consumes bytes of opcodes, and in the past, I used to struggle with every byte to keep my toy bootloader the "Space Shuttle" fit in the first boot block. At that time, with a program which was relatively short and had to stay all in 456 Bytes (512 byte of block minus the Bytes of the Bios Parameter Block minus 2 Bytes of boot signature), it was ok to keep the trace on a piece of paper of the values assumed by registers at each step and fit all pieces of the puzzle together. This technique is impossible to be used with code that grows in a modular way. When I wrote show_string_II, I was still not sure and wondering myself whether it was good to push and pop only the registers used or it was better to push and pop all registers in a sort of standardized way of beginning and ending a procedure. I liked the idea of a standardized opening and closing for the procedure that I could reuse everywhere, however, the useless pushing and popping of all other registers that didn't change seamed to be inefficient to me, especially when I thought of a calling chain from procedure to procedure each of them pushing all register to stack. I would eventually end with a huge stack queue with a lot of copies of registers. When I wrote show_string_II, I was still experimenting which way to follow and I had no strong experience that could have helped me decide in which direction to go.
Besides preserving the used registers by pushing them on the stack, I observed that the show_string procedure ended as soon as the Byte 0x00 was found and that it printed nothing on the screen if the very first Byte was 0x00. Based on this consideration I decided to check immediately whether or not the first Byte of the string pointed with DS:[SI] was 0x00, because I could avoid the execution of the procedure if it was like that. You can see here the procedure show_string_II and compare this one with the previous version of show_string. You find both procedures in the DOWNLOAD AREA.
Comments
Post a Comment