0

My problem is I am trying to take user input in a loop and every time I want to store that input into a place in the memory to access it later and print it with some changes. And I am being confused regarding how to first declare an array that can hold my 5 words for example, and later how to store the input every time into that array.

Exactly I am taking names of subjects: and the loop in c++ would look something like that:

string subjects_code[5]
for(int i=0; i<5; i++)
    cin>>subjects_code[i];   
   // like AFJS421 , CSFA424, SCSJ1023 and so on

I did my research all over the internet and YouTube, I found that you can't declare an array of strings in assembly, you basically have a single array of bytes followed by a null terminator. I understand that and I did my code with it and it is working, but the problem is I really need to store the 5 subjects codes into 5 different variables (or at least memory locations), because later after some calculations I need to print back those subjects.

    ;taking input from user: in a Loop   
    ;in .data I have subjects_code BYTE MAX DUP(?)
    MAX = 20
mov ebx,0
mov count, 5   ; cuz ReadString uses ecx as buffersize

InputLoop:
            ; This is just a prompt out, no need to worry about it

    mov ecx, MAX    
    mov edx, OFFSET Enter_code       ;  setting offset for prompt   


            ; temp variable to read into it, use it for assgining
    mov edx, OFFSET temp_subject_code  
    call ReadString                 ; reading the code into temp
    mov subjects_code+[ebx], temp_subject_code


    add ebx, 4
    mov ecx, count
    dec count

    Loop InputLoop

;---------------------------------------------------------------

After storing every string, I expect to do at the end of the program:

subject1: SCSJ134
subject2: SCSR231
Subject3: SCSI392

all the way up to Subject5.

1
  • The key difference between a C++ string and an assembly string is that in C++ the compiler and/or runtime library manage the memory for the string and allocate/copy memory as needed. When writing assembly code, you must take care of these details yourself. You can't simply assign one string to another, you have to write code to actually compute the location and copy the bytes. In this regard, C is a closer match than C++ to the capabilities of assembly language, so you may want to consider using C code instead of C++ as a prototype for your assembly code to get the steps right. Commented May 4, 2019 at 22:46

2 Answers 2

1

Here's one approach. This is the equivalent of the C code:

char subject_code[5][20];
for(int i=0; i<5; i++)
    ReadString(subject_code[i]);

.

    MAXLEN = 20
    COUNT = 5
    mov ebx,0

InputLoop:
    mov eax, MAXLEN
    mul ebx
    lea edx, subjects_code[eax]  
    mov ecx, MAXLEN-1
    call ReadString                 ; reading the code into subject_code[ebx]

    inc ebx
    cmp ebx, COUNT
    jnz InputLoop

    mov ebx, 0
OutputLoop:
    mov ecx, MAXLEN
    mov eax, ebx
    mul ecx ; this can be done without mul since MAXLEN is a constant
    lea edx, subjects_code[eax]
    call WriteString
    call Crlf

    inc ebx
    cmp ebx,COUNT
    jl OutputLoop

    .data
subjects_code BYTE MAXLEN*COUNT DUP(?)
Sign up to request clarification or add additional context in comments.

4 Comments

I tried this code it worked for the input, and for the output it went wrong by printing random stuff from the memeory and breaking later OutputLoop: mov ecx, MAXLEN mov eax, ebx mul ecx lea edx, subjects_code[eax] call WriteString inc ebx cmp ebx, COUNT jnz OutputLoop
I tried again: it worked perfectly mov ebx, 0 OutputLoop: mov ecx, MAXLEN mov eax, ebx mul ecx ; this can be done without mul since MAXLEN is a constant lea edx, subjects_code[eax] call WriteString call Crlf inc ebx cmp ebx,COUNT jle OutputLoop
Based on your comment on the other answer, I added “mov ecx, MAXLEN-1” before the call to ReadString, to avoid the possibility of a buffer overrun.
I added the working output loop to the answer for the convenience of future readers. Thanks for sharing that. I changed jle to jl, to avoid going one past the end of the array. (That bug probably showed up as an extra blank line in your output.)
1

Here's another approach. This is the equivalent of the C code:

char *subject_code[5];
for(int i=0; i<5; i++) {
    subject_code[i] = malloc(20);
    ReadString(subject_code[i]);
}

.

    MAXLEN = 20
    COUNT = 5
    mov ebx,0

InputLoop:
    mov ecx, MAXLEN
    call malloc
    mov subjects_code[ebx*4], eax
    mov edx, eax  
    mov ecx, MAXLEN
    call ReadString                 ; reading the code into subject_code[ebx]

    inc ebx
    cmp ebx, COUNT
    jnz InputLoop

    .data
subjects_code DWORD COUNT DUP(?)

4 Comments

Note that I omitted details such as error checking. I don't know whether ReadString null-terminates the string or returns the number of characters read, but if it does the latter then you would want to store that.
for this approach, it tells me that Malloc is not defined, I am using VisualStudio 2010 to compile ( it's the only way that worked for compiling), I am using Include Irvine32.inc
I also googled for read string and i got this: Reads a string of up to ECX non-null characters from standard input, stopping when the user presses the Enter key. A null byte is stored following the characters input, but the trailing carriage return and line feed characters are not placed into the buffer. ECX should always be smaller than the buffer size (never equal to the buffer size) because the null byte could be the (ECX+1)th character stored.
Sorry, I used “malloc” as a placeholder for whatever memory allocation function you have available. I guess you would use HeapAlloc? You’ll need to read up on what the calling sequence is; I haven’t used it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.