Search code examples
assemblyx86-64nasm

Nasm 64 Assembly column's even numbers total show on Array


I have matrix 5,5. I'm trying to print each column's even numbers total in an array(5). Can anyone help please? I got a segment error. Please don't tell me to start another language firstly. I'm trying this for almost 3 days. But I still couldn't find out the error. Please.

My expected answer is

2 8 8 0 24 0

This is my code:

    bits 64;

%include "../io.asm"



%define write 1
%define stdout 1
%define exit 60

section .data
  matr db 2,2,3,4,1
  db 5,1,5,8,1
  db 9,6,1,12,1
  db 7,3,15,1,1
  db 1,1,1,1,1

  space db " ", 10
  space_len equ $- space

section .bss
  temp resb 5

section .text
  global _start

  _start:
  mov r8, 0
  mov r9, -6

  print_output:
  add r9, 6
  mov rdx, 0

  column_loop:
  mov rax, [matr +r9]
  test rax, 1
  jnz next_element
  add rdx, rax

  next_element:
  add r9, 5
  loop column_loop

  add rdx, '0'
  mov [temp + r8], rdx

  ;mov rax, [matr + r9]
  ;mov rbx, [matr + 5 * r8 + 4 - r8]
  ;mul rbx

  ;add rax, '0'
  ;mov [temp + r8], rax

  inc r8
  cmp r8, 5
  je _exit
  jne print_output

  _exit:

  mov rsi, temp
  mov rdx, 5
  mov rax, write
  mov rdi, stdout
  syscall

  mov rax, write
  mov rdi, stdout
  mov rsi, space
  mov rdx, space_len
  syscall

  mov rax, exit
  xor rdi, rdi
  syscall

If you intresting what is io.asm is,

        section .text     ; ������� ����
IntToStr64: 
         push   rdi
         push   rbx
         push   rdx
         push   rcx
         push   rsi
         mov    byte[rsi],0 ; �� ����� �����
         cmp    eax,0
         jge    .l1
         neg    eax
         mov    byte[rsi],'-'
.l1      mov    byte[rsi+6],10
         mov    rdi,5
         mov    bx,10
.again:  cwd           ; ��������� ����� �� ��������
         div    bx     ; ����� ��������� �� 10
         add    dl,30h ; �������� �� ������� ��� �����
         mov    [rsi+rdi],dl ; ����� ������ � ������
         dec    rdi    ; ��������� ��������� ��  
                       ; ���������� �������
         cmp    ax, 0  ; ������������� ��� �����?
         jne    .again
         mov    rcx, 6
         sub    rcx, rdi ; ����� ����������+����
         mov    rax,rcx
         inc    rax    ; ����� ����������+OA
         inc    rsi    ; ���������� ����
         push   rsi
         lea    rsi,[rsi+rdi] ; ������ ����������
         pop    rdi
         rep movsb
         pop    rsi  
         pop    rcx
         pop    rdx
         pop    rbx
         pop    rdi
         ret
StrToInt64:
         push   rdi
         mov    bh, '9'
         mov    bl, '0'
         push   rsi     ; ��������� ����� �������� ������
         cmp    byte[rsi], '-'
         jne    .prod
         inc    rsi     ; ���������� ����
.prod    cld
         xor    di, di  ; �������� ������� �����
.cycle:  lodsb          ; ��������� ������ (�����)
         cmp    al, 10  ; ���� 10, �� �� �����
         je     .Return
         cmp    al, bl  ; ���������� � ����� ����
         jb     .Error  ; "����" � ������
         cmp    al, bh  ; ���������� � ����� ������ 
         ja     .Error  ; "����" � ������
         sub    al, 30h ; �������� ����� �� �������
         cbw            ; ��������� �� �����
         push   ax      ; ��������� � �����
         mov    ax, 10  ; ������� 10 � AX
         mul    di      ; ��������, ��������� � DX:AX
         pop    di      ; � DI � ��������� �����
         add    ax, di
         mov    di, ax  ; � DI � ����������� �����        
         jmp    .cycle
.Return: pop    rsi
         mov    rbx, 0
         cmp    byte[rsi], '-'
         jne    .J
         neg    di
.J       mov    ax, di
         cwde
         jmp    .R
.Error:  pop    rsi
         mov    rax, 0
         mov    rbx, 1
.R       pop    rdi
         ret

Please don't close my question. I highly appreciate everyone's answers

I got a segment error, but I can't fix it.
I'm trying to get output as

2 8 8 0 24


Solution

  • 2 8 8 0 24 0
    
    2 8 8 0 24
    

    These 'expected results' that you show us are not what the program would have to output. The correct result will be: 2 8 0 24 0

    loop column_loop
    

    The loop instruction depends on the RCX register and you forgot to initialize it! Therefore your loop will have run for much too long, addressing memory beyond what is allowed and thus triggering Segmentation Error.

    print_output:
      add r9, 6
    

    This peculiar addition is another reason why you reach memory that is beyond the array. The inner loop already has raised R9 by 25 (5 x 5), and then you add another 6. What you could need is restoring R9 and then adding 1, possibly using push and pop. Alternatively, you could subtract 24 from R9. But by far the simplest solution would be to initialize R9 to the current value in R8.

    matr db 2,2,3,4,1
         db 5,1,5,8,1
         db 9,6,1,12,1
         db 7,3,15,1,1
         db 1,1,1,1,1
    

    Your matrix contains byte-sized data. You need to read the elements as such. Instead of mov rax, [matr +r9] that reads 8 bytes, use movzx eax, byte [matr + r9]. This will read a single byte and extend it into the full RAX register.

    My suggestion for the nested loop

      xor   edi, edi                    ; Output offset [0,4]
    OuterLoop:
      mov   esi, edi                    ; Input offset [0,24]
      xor   edx, edx
    InnerLoop:
      movzx eax, byte [matr + rsi]
      test  al, 1
      jnz   IsOdd
      add   edx, eax
    IsOdd:
      add   esi, 5                      ; To next row
      cmp   esi, 25                     ; Is replacement for
      jb    InnerLoop                   ;  the slow `LOOP`
      add   edx, '0'                    ; (*)
      mov   [temp + rdi], dl            ; Only writing a single byte!
      inc   edi
      cmp   edi, 5
      jb    OuterLoop
    

    (*) Expected output

    280H0 
    

    The sum for the 4th column is 24. This cannot get displayed as a single digit via add edx, '0'. I see that you already have a code IntToStr64 that could be useful for the conversion.