Search code examples
assemblymasm

Assembler Work With Strings


A task:

Make program which, Shows the last 20 characters. I did but, program work only with 47 length string. How to make universal program for work with any length of a line.

MASM:

.model small
.stack 100h
.data 
Original_string db 'Assembler language is the fatster in the world.',13,10,'$'
Formed_line db 255 DUP(?)

.code
.386
main:
mov ax,@data;
mov ds,ax;
mov es,ax;

mov dx,offset Original_string
mov ah, 9
int 21h

cld
mov ecx,LENGTHOF Original_string
sub ecx, 27                     ;47-20 =17
mov esi,[OFFSET Original_string]+27
mov edi,OFFSET Formed_line
rep movsb

mov dx,offset Formed_line
mov ah,9
int 21h
mov ax,4C00h
int 21h
end main

Thank you.


Solution

  • "fatster" - the International Assembly language committee disapproves this, and the on going diet was deemed rather successful.

    To make the values 47,20,27 less hard-wired in the code, minimize their use in code.


    mov ecx,LENGTHOF Original_string
    

    is input argument, something like this will be always there, even if you take input string from user (then instead of mov ecx,<number> you would have to call some sort of strlen function). = OK


    sub ecx, 27                     ;47-20 =17
    

    27 is not related to task "display last 20 chars", do it other way.


    mov esi,[OFFSET Original_string]+27
    

    The address of start of string is again input argument, and in some form it has to be provided to code either way, but the +27 is again some hard-coded intermediate value.


    Basically you should be able to do the task with this input (starting sequence, after displaying the string on screen):

    mov   esi,OFFSET Original_string
    mov   ecx,LENGTHOF Original_string
    

    Every further code should reuse those argument values only, never again using Original_string label, and only using 20 constant (because task is "last 20 characters"). Try to calculate every other intermediate value you need from these 3 basic values (keep copy of values which you have to access several times).

    Actually to print last 20 chars from original string with those input is easier than one may expect. As the string is already terminated by '$' at end, you can just:

    lea   edx,[esi+ecx-20]
    mov   ah, 9
    int   21h
    

    Done. esi+ecx is address of end() of string (the first byte after '$'), then -20 will move the address 20 characters back.

    Actually you should do probably -21, because '$' is not character of string, but string terminator. So -20 is displaying just 19 characters (including <EOL> chars).

    And for generic algorithm taking any input you should test first, if ecx is at least 21+, for shorter/empty strings the -21 address would go outside of string.

    If you would have to display first 20 chars, then you would need either to modify original string by destroying the 21th char of it with '$' terminator, or output it char-by-char (int 21h,ah=2 for example) and count 20, or copy it in memory into Formed_line and add terminator, but none of that is needed for "last 20 chars", that string is ready to be printed in memory as is, just move the beginning.