Related
This question already has answers here:
What does "int 0x80" mean in assembly code?
(9 answers)
Assembly (x86): <label> db 'string',0 does not get executed unless there's a jump instruction
(2 answers)
How to represent octal numbers in Assembly?
(2 answers)
How to make the kernel for my bootloader?
(1 answer)
Closed 3 months ago.
I am trying to get my C program to run on a computer with no operating system. I have a version of an MBR that just prints a (!), but when i try to add code to run my C program, as shown here the machine just reboots infinitely.
I only just got the assembly to compile because i took out some definitions and just put the numbers where it says //here
Here is my code:
`
[org 0x7c00]
mov [BOOT_DISK], dl
CODE_SEG equ GDT_code - GDT_start
DATA_SEG equ GDT_data - GDT_start
cli
lgdt [GDT_descriptor]
mov eax, cr0
or eax, 1
mov cr0, eax
jmp CODE_SEG:start_protected_mode
jmp $
GDT_start:
GDT_null:
dd 0x0
dd 0x0
GDT_code:
dw 0xffff
dw 0x0
db 0x0
db 0b10011010
db 0b11001111
db 0x0
GDT_data:
dw 0xffff
dw 0x0
db 0x0
db 0b10010010
db 0b11001111
db 0x0
GDT_end:
GDT_descriptor:
dw GDT_end - GDT_start - 1
dd GDT_start
[bits 32]
start_protected_mode:
mov al, '!'
mov ah, 0x0f
mov [0xb8000], ax
;open the file for reading
mov eax, 5
file_name db 'e.exe'
mov ebx, file_name
mov ecx, 0 ;for read only access
mov edx, 0777 ;read, write and execute by all
int 0x80
;read from file
mov eax, 3
mov ebx, 1 //here
mov ecx, 26 //here
mov edx, 26 //here
int 0x80
jmp $
BOOT_DISK: db 0
times 510-($-$$) db 0
dw 0xaa55
`
this image showcase the error im getting when running the command "bochs" in the bootDIr directory where my assembly file , the image ,the binary and the script are at , the tutorial i watched was using ubuntu while im using kali,i dont think that was relevant but i would love your help
the goal is to show the "Hello" String when booting (+some messages generated by the emulator)
here is the nasm code:
[BITS 16]
[ORG 0x7c00]
start :
xor ax,ax
mov ds,ax
mov es,ax
mov ss, ax
mov sp, 0x7c00
PrintMessage :
mov ah,0x13
mov al, 1
mov bx,0xa
xor dx,dx
mov bp, Message
mov cx, MessageLen
int 0x10
End :
hlt
jmp End
Message : db "Hello"
MessageLen : equ $-Message
times (0x1be -($-$$)) db 0
db 80h
db 0,2,0
db 0f0h
db 0ffh,0ffh,0ffh
dd 1
dd (20*16*63 - 1 )
times (16*3) db 0
db 0x55
db 0xaa
I am trying for hours and hours to access an array in assembly x86 TASM using dosbox - but I always get 'Operand types do not match' or 'Pointer expression needs brackets' error - I've searched the whole internet and couldn't find something that works in TASM x86.. this is the code:
IDEAL
MODEL small
STACK 100h
DATASEG
; --------------------------
A DB 1, 2, 3, 4, 5, 6, 7, 8, 10, 11
; --------------------------
CODESEG
start:
mov ax, #data
mov ds, ax
; --------------------------
mov al,A[0]
; --------------------------
exit:
mov ax, 4c00h
int 21h
END start
Changing the line to:
mov ax, BYTE PTR A[0]
or to:
mov ax, A[BYTE PTR 0]
And even changing ax or al with all these combinations is failing.. or trying to acces the OFFSET of array A:
mov al, A[OFFSET A]
I don't know where's the problem..
Thank you for helping!
I was going to post this on codereview.stackexchange.com but the problem is this code does not work correctly.
I have an AT89C4051 processor which only has one hardware UART, however I will attach two UART-based devices to it of which one is my computer. The configuration across all devices is 9600,N,8,1 (9600bps, no parity, 8 data bits, 1 stop bit)
I attempted to create two software-based UARTs with machine-optimized code that can interface between the two devices, however the data I received on my computer is incorrect.
I was expecting 'ABCD' or 'abcd' to appear on the screen but all I received was 'DDDD'.
What can I do here to fix this problem without resorting to buying extra hardware?
;dual 9600bps channels
;RX1,TX1 = uart channel
;RX2,TX2 = uart channel
;start with uart configuration
org 0000h
ljmp uartcfg
;every 1/2 bit time execute function
org 000Bh
sjmp swuartint
SWCFG equ 20h ;serial config
;config for uart 1
SWRI bit 20h.0 ;data fully received if SWRI set
serrxslow bit 20h.2 ;bit flip-flop for receive. cpl 2x = 1 full bit time
SWTI bit 20h.1 ;data fully transmitted if SWTI set
sertxslow bit 20h.3 ;bit flip-flop for transmit. cpl 2x = 1 full bit time
;config for uart 2: same format
SWRI2 bit 20h.4
serrxslow2 bit 20h.6
SWTI2 bit 20h.5
sertxslow2 bit 20h.7
SWUARTNO bit 21h.0 ;current Software Uart Number
SWRNR bit 21h.1 ;Software Uart Receiver Not Ready
SWTMP equ 0Fh ;Temporary variable to pass indirect address value to register
SBUFR2 equ 0Eh ;Uart 2 received byte value
SBUFR equ 0Dh ;Uart 1 received byte value
SBUFT2 equ 0Ch ;Uart 2 sent byte value
SBUFT equ 0Bh ;Uart 1 sent byte value
swuartint:
;1/2 bit time detected.
;save registers
push PSW
push ACC
;set register bank RS1:RS0 = 1:1 or 1:0 depending on UART wanted
;so we have our own private set of R0-R7 variables for each UART
setb RS1
mov C,SWUARTNO
mov RS0,C
;Get bit from UART 2
mov C,RX2
jb RS0,nour1
mov C,RX1 ;Get bit from UART 1 if RS0 not set
nour1:
jb SWTI,extx
;Transmit routine is only used if transmit complete flag is NOT set.
cpl sertxslow
jnb sertxslow,extx
;Only do the real transmit work on full bit times
;save existing carry flag (it has received value)
push PSW
mov A,R2 ;R2=transmit counter to load
jnz tnz
;Counter=0: Load transmitted value to R3 through temporary variable
mov SWTMP,#R1
mov R3,SWTMP
;Set counter to 1 and clear C to output start bit (of 0)
inc A
clr C
sjmp extx1
tnz:
jnb ACC.3,tne
jnb ACC.0,tne
;Counter is 9 so set transmit complete flag
setb SWTI
clr A ;set counter to 0 and set C to output stop bit (of 1)
setb C
sjmp extx1
tne:
;Counter is between 1 and 8
;Save accumulator to R5 since push/pop wastes cycles
mov R5,A
mov A,R3 ;load accumulator with outgoing data
RRC A ;shift out one byte to C
mov R3,A ;save data
mov A,R5
inc A ;increment count
extx1:
;Use right transmit channel based on chosen UART number
jb RS0,nour2
mov TX1,C
sjmp extx2
nour2:
mov TX2,C
extx2:
;Save count
mov R2,A
;and load back receiver value C
pop PSW
extx:
mov A,R7 ;load receiving count
jnz rnz
;Counter=0. Store ready status
mov SWRNR,C
jc exrx
;increment counter only if start bit=0
inc A
clr serrxslow ;reset flip flop so we wait 1 bit time to get bit.
sjmp exrx
rnz:
cpl serrxslow
jb serrxslow,exrx
;Counter > 0, 1 bit time waited
jnb ACC.3,rne
jnb ACC.0,rne
;Counter = 9. Status = Stop bit. 1=complete. 0=fail.
mov SWRI,C
;Store data
mov SWTMP,R4
mov #R0,SWTMP
;Clear count
clr A
sjmp exrx
rne:
;Counter = 1 to 8.
;Load data same way as transmit routine
mov R6,A
mov A,R4
RRC A
mov R4,A
mov A,R6
inc A ;increment count
exrx:
mov R7,A ;save count to receive count variable
;Don't switch UARTs when in the middle of a bit time
jnb sertxslow,nextuart
;Don't switch UARTs if receiver has data to process
jnb SWRNR,nextuart
;Don't switch UARTs if transmitter has data to process
jnb SWTI,nextuart
;Switch UART
cpl SWUARTNO
;Flip nibbles in configuration as each nibble
;belongs to its own UART
mov A,SWCFG
swap A
mov SWCFG,A
nextuart:
;restore registers and exit
pop ACC
pop PSW
reti
uartcfg:
setb RS1
setb RS0
mov R0,#SBUFR2 ;If RS1=RS0=1, #R0 = contents of SBUFR2
mov R1,#SBUFT2 ;If RS1=RS0=1, #R1 = contents of SBUFT2
clr RS0
mov R0,#SBUFR ;If RS1=1 and RS0=0, #R0 = contents of SBUFR
mov R1,#SBUFT ;If RS1=1 and RS0=0, #R1 = contents of SBUFT
clr RS1 ;Restore register bank (RS1=0, RS0=0)
mov SWCFG,#22h ;Set transmit complete to both UARTs at once
mov TH0,#0A0h ;Value = 256-(((crystal/baud)/12)/2) = 9.6kbps 1/2 bit rate
mov TL0,#0A0h
mov TMOD,#22h ;8-bit timers auto reload
mov SP,#50h ;get stack pointer away from our work
setb TR0 ;enable timer
mov IE,#082h ;enable Timer 0 interrupt
ljmp startapp ;go to program
;serial port 1
;plugged into computer for data testing
RX1 equ P3.0
TX1 equ P3.1
;serial port 2
RX2 equ P3.3
TX2 equ P1.2
startapp:
; Trying to output 'ABCD' or 'abcd' but all I get is 'DDDD'
mov SBUFT,#0h ;Set character for UART 1
clr SWTI ;clear complete flag
jnb SWTI,$ ;stall until character transmitted
mov SBUFT,#'A' ;repeat...
clr SWTI
jnb SWTI,$
mov SBUFT,#'B'
clr SWTI
jnb SWTI,$
mov SBUFT,#'C'
clr SWTI
jnb SWTI,$
mov SBUFT,#'D'
clr SWTI
jnb SWTI,$
mov SBUFT2,#0h ;Set character for UART 2
clr SWTI2 ;clear complete flag
jnb SWTI2,$ ;stall until character transmitted
mov SBUFT2,#'a' ;repeat...
clr SWTI2
jnb SWTI2,$
mov SBUFT2,#'b'
clr SWTI2
jnb SWTI2,$
mov SBUFT2,#'c'
clr SWTI2
jnb SWTI2,$
mov SBUFT2,#'d'
clr SWTI2
jnb SWTI2,$
sjmp $
I'm programming a MSP430 in C language as a simulation of real microcontroller. I got stuck in addressing modes (https://en.wikipedia.org/wiki/TI_MSP430#MSP430_CPU), especially:
Addressing modes using R0 (PC)
Addressing modes using R2 (SR) and R3 (CG), special-case decoding
I don't understand what does mean 0(PC), 2(SR) and 3(CG). What they are?
How to check these values?
so for the source if the as bits are 01 and the source register bits are a 0 which is the pc for reference then
ADDR Symbolic. Equivalent to x(PC). The operand is in memory at address PC+x.
if the ad bit is a 1 and the destination is a 0 then also
ADDR Symbolic. Equivalent to x(PC). The operand is in memory at address PC+x.
x is going to be another word that follows this instruction so the cpu will fetch the next word, add it to the pc and that is the source
if the as bits are 11 and the source is register 0, the source is an immediate value which is in the next word after the instruction.
if the as bits are 01 and the source is a 2 which happens to be the SR register for reference then the address is x the next word after the instruction (&ADDR)
if the ad bit is a 1 and the destination register is a 2 then it is also an &ADDR
if the as bits are 10 the source bits are a 2, then the source is the constant value 4 and we dont have to burn a word in flash after the instruction for that 4.
it doesnt make sense to have a destination be a constant 4 so that isnt a real combination.
repeat for the rest of the table.
you can have both of these addressing modes at the same time
mov #0x5A80,&0x0120
generates
c000: b2 40 80 5a mov #23168, &0x0120 ;#0x5a80
c004: 20 01
which is
0x40b2 0x5a80 0x0120
0100000010110010
0100 opcode mov
0000 source
1 ad
0 b/w
11 as
0010 destination
so we have an as of 11 with source of 0 the immediate #x, an ad of 1 with a destination 2 so the destination is &ADDR. this is an important experiment because when you have 2 x values, a three word instruction basically which one goes with the source and which the destination
0x40b2 0x5a80 0x0120
so the address 0x5a80 which is the destination is the first x to follow the instruction then the source 0x0120 an immediate comes after that.
if it were just an immediate and a register then
c006: 31 40 ff 03 mov #1023, r1 ;#0x03ff
0x4031 0x03FF
0100000000110001
0100 mov
0000 source
0 ad
0 b/w
11 as
0001 dest
as of 11 and source of 0 is #immediate the X is 0x03FF in this case the word that follows. the destination is ad of 0
Register direct. The operand is the contents of Rn
where destination in this case is r1
so the first group Rn, x(Rn), #Rn and #Rn+ are the normal cases, the ones below that that you are asking about are special cases, if you get a combination that fits into a special case then you do that otherwise you do the normal case like the mov immediate to r1 example above. the destination of r1 was a normal Rn case.
As=01, Ad=1, R0 (ADDR): This is exactly the same as x(Rn), i.e., the operand is in memory at address R0+x.
This is used for data that is stored near the code that uses it, when the compiler does not know at which absolute address the code will be located, but it knows that the data is, e.g., twenty words behind the instruction.
As=11, R0 (#x): This is exactly the same as #R0+, and is used for instructions that need a word of data from the instruction stream. For example, this assembler instruction:
MOV #1234, R5
is actually encoded and implemented as:
MOV #PC+, R5
.dw 1234
After the CPU has read the MOV instruction word, PC points to the data word. When reading the first MOV operand, the CPU reads the data word, and increments PC again.
As=01, Ad=1, R2 (&ADDR): this is exactly the same as x(Rn), but the R2 register reads as zero, so what you end up with is the value of x.
Using the always-zero register allows to encode absolute addresses without needing a special addressing mode for this (just a special register).
constants -1/0/1/2/4/8: it would not make sense to use the SR and CG registers with most addressing modes, so these encodings are used to generate special values without a separate data word, to save space:
encoding: what actually happens:
MOV #SR, R5 MOV #4, R5
MOV #SR+, R5 MOV #8, R5
MOV CG, R5 MOV #0, R5
MOV x(CG), R5 MOV #1, R5 (no word for x)
MOV #CG, R5 MOV #2, R5
MOV #CG+, R5 MOV #-1, R5