Author Topic: [SOLVED] Dealing with virtual and raw addresses (avoid the use of the linker)  (Read 24959 times)

Offline ;

  • Jr. Member
  • *
  • Posts: 9
Greetings NASM community !
Since I'm a beginner with NASM (but not in ASM and PE format that I know very well), I don't find some informations I need in the documentation :

How can we get the current raw position, or file offset, after changing the virtual adress ? For examples, when a "vstart" from "segment" has been called, or when a "org" is defined".

Is there a way to define a dynamic virtual positionning, even by using macro tricks if needed ? I mean, a kind of "align" version for virtual addresses ?

Thanks for your responses.
Sincerely.



EDIT for answers :

Getting the raw file offset : way is still unknown.
Dynamic virtual positionning : way is given by Steve here.

.
« Last Edit: July 20, 2013, 10:31:07 AM by ; »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #1 on: July 10, 2013, 10:03:52 PM »
Hi ; - heck of a name you've got there!

I'm not sure I understand the question. Can you gave an example of what you're trying to do? Did we see you over at Stack Overflow? Trying to translate some stuff from Fasm? In any case, there's some discussion over there... I'm not sure anyone came up with a definitive answer...

Best,
Frank


Offline ;

  • Jr. Member
  • *
  • Posts: 9
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #2 on: July 11, 2013, 12:46:53 AM »
Yeah, I like this semi-colon nick name on the left too, cause it means that all the text of my post is comment. 8)

Thanks for your reply, and sorry for the bad explanation of my problem.
Here is the end of my asm file :

Code: [Select]
sectionHeaders:

    db ".text", 0, 0, 0          ; Name
    dd SECTION_ALIGN(RAW_CODE.SIZE) ; VirtualSize
    dd code                      ; VirtualAddress
    dd RAW_CODE.SIZE            ; SizeOfRawData
    dd RAW_CODE                  ; PointerToRawData
    dd 0                        ; PointerToRelocations
    dd 0                        ; PointerToLinenumbers
    dw 0                        ; NumberOfRelocations
    dw 0                        ; NumberOfLinenumbers
    dd 0x60000020                ; Characteristics

    db ".data", 0, 0, 0          ; Name
    dd SECTION_ALIGN(RAW_DATA.SIZE) ; VirtualSize
    dd data                      ; VirtualAddress
    dd RAW_DATA.SIZE            ; SizeOfRawData
    dd RAW_DATA                  ; PointerToRawData
    dd 0                        ; PointerToRelocations
    dd 0                        ; PointerToLinenumbers
    dw 0                        ; NumberOfRelocations
    dw 0                        ; NumberOfLinenumbers
    dd 0xC0000040                ; Characteristics

align FILE_ALIGNMENT, db 0

RAW_HEADER.SIZE equ $ - header



; ******************************************************************************************************



RAW_CODE equ RAW_HEADER.SIZE

section .text vstart=SECTION_ALIGN($)

code:

; (code here)

entryPoint:

xor eax, eax
ret

; (code here too)

align FILE_ALIGNMENT, db 0

RAW_CODE.SIZE equ $ - code



; ******************************************************************************************************



RAW_DATA equ RAW_CODE + RAW_CODE.SIZE

section .data vstart=SECTION_ALIGN($)

data:

; (initialized data here)

align FILE_ALIGNMENT, db 0

RAW_DATA.SIZE equ $ - data



; ******************************************************************************************************



IMAGE_SIZE equ SECTION_ALIGN($)

Note : "SECTION_ALIGN()" is a defined function that transform an address to an aligned offset.

My aims are :

- Generate automatically some variables at "sectionHeaders" label with relevant values. (It concerns dwords which comment lines are : "VirtualSize", "VirtualAddress", "SizeOfRawData", "PointerToRawData") ;
- Set the ".code" and ".data" segments offsets to aligned virtual addresses depending on the size of previous content.

Said simply and quickly, I want to use the "bin" compilation mode in order to build an exe file, but with headers filled without hardcoding.

Of course, my code cannot work because I don't respect the NASM parser priorities.
So, what can I do in order to make it ? Is there a way to fix my attempts ?

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #3 on: July 11, 2013, 09:22:27 AM »
Mmmm... well this won't assemble for lack of SECTION_ALIGN (and other things), of course. Do you have SECTION_ALIGN, or is that what you need?

I'm going to cop out on this and refer you to:

http://home.myfairpoint.net/fbkotler/nagoa20120202.zip

This is the old "nagoa+.inc", updated to assemble with "new Nasm". I'm listed as a contributor. I recall that Numit_or's PEMACS had a glitch in the dos stub with not setting ds. "push cs"/"pop ds" fixed it. I think that may be my entire contribution. :)

More recently, there were complaints that Nasm would no longer assemble it. Old Nasm was a bit casual with "context-local variables". If the variable wasn't found within the current context, it would look outside the context. This wasn't really the intended behavior, and "new Nasm" will burp up an error if the variable is not found in the context it's supposed to be local to. "nagoa+inc" did this - assigned a context-local variable before creating the context. Put the variable inside the context - fixed!

I see another change which may be more relevant to your problem. I changed "alignb SECTION"/ "_bss_vsize equ $ - $$" to "_bss_vsize equ _round($ - $$)". I don't recall why I made that change. That "_round()" macro may be of interest to you, although I don't think it's exactly what you want.

Where you've got "SECTION_ALIGN(...)", nagoa+.inc seems to use just "dd  _data_vsize", etc. These appear to be defined in the "end" macro (presumably needs to be the last thing in the file) which just re-enters each section and (with some alignment), calculates "$ - $$" - the length of the section. If you've already got labels at the ends of your sections, you can probably avoid having to use an "end" macro.

I'm afraid at this point I don't even remember if I knew more about the PE format and have forgotten it, or if I never knew. :) Nevertheless, if you show what you're using for SECTION_ALIGN and what Nasm has to say about it, I might be able to help you get Nasm to "shut up and assemble". If I've missed the problem entirely, sorry - try again.

Best,
Frank


Offline ;

  • Jr. Member
  • *
  • Posts: 9
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #4 on: July 11, 2013, 05:59:23 PM »

Oh this nagoa define even the windows api, what an impressive job !
Thanks a lot for this goldmine.

Well, I read about virtual address :

Code: [Select]
;-----------------------------------------------------------------------------
; Address calculation macros:
; Thanks to S_Tec of Northern Dragons
;-----------------------------------------------------------------------------

; Round a physical size up to a virtual size:
%define _round(size) (( size + SECTION-1 ) & ~(SECTION-1))

; Make an RVA out of a label in the .text section:
%define __rva(label) _head_vsize + label - _text_start

The "_round()" macro is a very smart version of what I called "SECTION_ALIGN()" !
(However, we have to be carful with "_round(0)" that returns "~(SECTION-1)" instead of zero)



So, stealing this function (^^,) and following your advices, I tried with the folloing code :

Code: [Select]
; exetest.asm

SECTIONS equ 2
TIME_DATE equ 0

IMAGE_BASE      equ 0x400000
SECTION_ALIGNMENT equ   0x1000
FILE_ALIGNMENT  equ    0x200

BSS_SIZE equ 0



%define nagoa_round(size) ((size + SECTION_ALIGNMENT - 1) & ~(SECTION_ALIGNMENT - 1))



bits 32
org IMAGE_BASE



; ******************************************************************************************************



header:

dw "MZ"                  ; e_magic
dw 0                    ; e_cblp
dw 0                    ; e_cp
dw 0                    ; e_crlc
dw 0                    ; e_cparhdr
dw 0                    ; e_minalloc
dw 0                    ; e_maxalloc
dw 0                    ; e_ss
dw 0                    ; e_sp
dw 0                    ; e_csum
dw 0                    ; e_ip
dw 0                    ; e_cs
dw 0                    ; e_lsarlc
dw 0                    ; e_ovno
dq 0                    ; e_res
dw 0                    ; e_oemid
dw 0                    ; e_oeminfo
dq 0, 0                  ; e_res2
dd imageHeader - IMAGE_BASE ; e_lfanew



imageHeader:

dd "PE"              ; Signature
dw 0x014C            ; Machine
dw SECTIONS          ; NumberOfSections
dd TIME_DATE        ; TimeDateStamp
dd 0                ; PointerToSymbolTable
dd 0                ; NumberOfSymbols
dw optionalHeader.SIZE ; SizeOfOptionalHeader
dw 0x0303            ; Characteristics



optionalHeader:

    dw 0x10B                    ; Magic
    db 0                        ; MajorLinkerVersion
    db 0                        ; MinorLinkerVersion
    dd nagoa_round(RAW_CODE.SIZE) ; SizeOfCode
    dd nagoa_round(RAW_DATA.SIZE) ; SizeOfInitializedData
    dd nagoa_round(BSS_SIZE)    ; SizeOfUninitializedData
    dd entryPoint - IMAGE_BASE  ; AddressOfEntryPoint
    dd code - IMAGE_BASE        ; BaseOfCode
    dd data - IMAGE_BASE        ; BaseOfData
    dd IMAGE_BASE                ; ImageBase
    dd SECTION_ALIGNMENT        ; SectionAlignment
    dd FILE_ALIGNMENT            ; FileAlignment
    dw 4                        ; MajorOperatingSystemVersion
    dw 0                        ; MinorOperatingSystemVersion
    dw 0                        ; MajorImageVersion
    dw 0                        ; MinorImageVersion
    dw 4                        ; MajorSubsystemVersion
    dw 0                        ; MinorSubsystemVersion
    dd 0                        ; Win32VersionValue
    dd IMAGE_END - IMAGE_BASE    ; SizeOfImage
    dd RAW_HEADER.SIZE          ; SizeOfHeaders
    dd 0                        ; CheckSum
    dw 2                        ; Subsystem
    dw 0                        ; DllCharacteristics
    dd 0x40000                  ; SizeOfStackReserve
    dd 0x6000                    ; SizeOfStackCommit
    dd 0x100000                  ; SizeOfHeapReserve
    dd 0x1000                    ; SizeOfHeapCommit
    dd 0                        ; LoaderFlags
    dd 16                        ; NumberOfRvaAndSizes
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_EXPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_IMPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_RESOURCE
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_EXCEPTION
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_SECURITY
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_BASERELOC
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_DEBUG
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_COPYRIGHT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_GLOBALPTR
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_TLS
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_IAT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
dd 0, 0                      ; reserved



optionalHeader.SIZE equ $ - optionalHeader



sectionHeaders:

    db ".text", 0, 0, 0          ; Name
    dd nagoa_round(RAW_CODE.SIZE) ; VirtualSize
    dd code                      ; VirtualAddress
    dd RAW_CODE.SIZE            ; SizeOfRawData
    dd RAW_CODE.OFFSET          ; PointerToRawData
    dd 0                        ; PointerToRelocations
    dd 0                        ; PointerToLinenumbers
    dw 0                        ; NumberOfRelocations
    dw 0                        ; NumberOfLinenumbers
    dd 0x60000020                ; Characteristics

    db ".data", 0, 0, 0          ; Name
    dd nagoa_round(RAW_DATA.SIZE) ; VirtualSize
    dd data                      ; VirtualAddress
    dd RAW_DATA.SIZE            ; SizeOfRawData
    dd RAW_DATA.OFFSET          ; PointerToRawData
    dd 0                        ; PointerToRelocations
    dd 0                        ; PointerToLinenumbers
    dw 0                        ; NumberOfRelocations
    dw 0                        ; NumberOfLinenumbers
    dd 0xC0000040                ; Characteristics

align FILE_ALIGNMENT, db 0

RAW_HEADER.SIZE equ $ - header



; ******************************************************************************************************



section .text vstart=nagoa_round($)

code:

entryPoint:

xor eax, eax
ret



align FILE_ALIGNMENT, db 0

RAW_CODE.OFFSET equ RAW_HEADER.SIZE
RAW_CODE.SIZE equ $ - code



; ******************************************************************************************************



section .data vstart=nagoa_round($)

data:

db "An unused string"

align FILE_ALIGNMENT, db 0

RAW_DATA.OFFSET equ RAW_CODE.OFFSET + RAW_CODE.SIZE
RAW_DATA.SIZE equ $ - data



; ******************************************************************************************************



IMAGE_END equ nagoa_round($)

Unfortunately, it gives the following errors :

Quote
exetest.asm:193: error: `&' operator may only be applied to scalar values

Which concerns the last line in the file : "IMAGE_END equ nagoa_round($)"
And :

Quote
exetest.asm:153: error: `&' operator may only be applied to scalar values
exetest.asm:176: error: `&' operator may only be applied to scalar values

Refering to both declarations of sections : "section .text vstart=nagoa_round($)", "section .data vstart=nagoa_round($)"

What's going on ?



Another problem is I don't like the way RAW_CODE.OFFSET and RAW_DATA.OFFSET are defined. Their computation are based on the previous sizes and offsets, but I would have preferred a command from NASM which can directly give the current offset in the binary file (like $ returns the current virtual offset).
Maybe such a command exists and I didn't found it yet ?



Although once again, thanks for all your help.
Best regards,
;

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #5 on: July 12, 2013, 01:54:42 PM »
You won't find the word "scalar" anywhere in the Manual - only in the error message. What it means is "not a relocatable value". Any label, including "$" is a relocatable value. Ordinarily, Nasm would put a label in a "list" to be passed to the linker, which would "patch" the value to reflect its final position.

In the case of "-f bin" output format, Nasm "acts as its own linker". Nasm eventually knows what "$" is going to be, but this happens in a separate module, much later in the processing than "$" would have to be known to do any manipulation of it. In theory, I think outbin.c could have a function "tell me where this will eventually be", to be called from the parser(?). This would require a lot of "special case" code (obviously we can't ask a separate linker), and I doubt very much if it'll ever happen.

The difference between two labels is a "scalar value" and Nasm can cope with it. You'll often see "$ -$$" ("$$" is "beginning of section") but other labels can be used. These two labels have to be in the same section (for the same reason), which is why RAW_CODE_OFFSET, etc. have to be calculated as "$ - $$" (size of this section) plus (size of previous sections) calculated and made an equate in previous sections.

I'm not aware of any way around this... except, of course, to let the linker do the job it was designed to do. I think it's quite cool that Nasm can produce an executable without the assistance of a linker (there are similar macros to do this for ELF code), but I have (somewhat reluctantly) concluded that it's better - more flexible - to use a linker for its intended purpose. YMMV.

Best,
Frank



Offline s_dubrovich

  • Jr. Member
  • *
  • Posts: 8
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #6 on: July 14, 2013, 04:36:29 AM »
a) I take it that the header is a part of the image, so you have to define it as section .text and use section .code for the code.  Otherwise the header gets folded into the code section.  If code is written without a section directive, then its default is given as section .text, section .text gets placed first in the image - 'follows=' doesn't work for trying to change its natural order.

b)  the vstart is needed if you want addresses in the section to org at zero, otherwise the addresses follow the previous named section.  ( all .text section are grouped, all .data sections are grouped, but .data follows .text, so the last .text section should end with the ALIGN ).

See if this gets you closer..

make file contained:

-f bin
-l exetest3.lst
-o exetest3.bin
-Z exetest3.err
exetest3.nsm

Code: [Select]
; exetest3.nsm
[MAP ALL exetest3.map] ;; use this to generate a MAP file of useful information.

SECTIONS equ 2
TIME_DATE equ 0

IMAGE_BASE      equ 0x400000
SECTION_ALIGNMENT equ   0x1000
FILE_ALIGNMENT  equ    0x200

BSS_SIZE equ 0

%define nagoa_round(size) ((size + SECTION_ALIGNMENT - 1) & ~(SECTION_ALIGNMENT - 1))

bits 32
org IMAGE_BASE

; ******************************************************************************************************

SECTION .text ;; if the header is part of the image, define it as section .text because .text is put
;; first in the image, and rename the code section as section .code
header:

dw "MZ"                  ; e_magic
dw 0                    ; e_cblp
dw 0                    ; e_cp
dw 0                    ; e_crlc
dw 0                    ; e_cparhdr
dw 0                    ; e_minalloc
dw 0                    ; e_maxalloc
dw 0                    ; e_ss
dw 0                    ; e_sp
dw 0                    ; e_csum
dw 0                    ; e_ip
dw 0                    ; e_cs
dw 0                    ; e_lsarlc
dw 0                    ; e_ovno
dq 0                    ; e_res
dw 0                    ; e_oemid
dw 0                    ; e_oeminfo
dq 0, 0                  ; e_res2
dd imageHeader - IMAGE_BASE ; e_lfanew

imageHeader:

dd "PE"              ; Signature
dw 0x014C            ; Machine
dw SECTIONS          ; NumberOfSections
dd TIME_DATE        ; TimeDateStamp
dd 0                ; PointerToSymbolTable
dd 0                ; NumberOfSymbols
dw optionalHeader.SIZE ; SizeOfOptionalHeader
dw 0x0303            ; Characteristics

optionalHeader:

    dw 0x10B                    ; Magic
    db 0                        ; MajorLinkerVersion
    db 0                        ; MinorLinkerVersion
    dd nagoa_round(RAW_CODE.SIZE) ; SizeOfCode
    dd nagoa_round(RAW_DATA.SIZE) ; SizeOfInitializedData
    dd nagoa_round(BSS_SIZE)    ; SizeOfUninitializedData
    dd entryPoint - IMAGE_BASE  ; AddressOfEntryPoint
    dd code - IMAGE_BASE        ; BaseOfCode
    dd data - IMAGE_BASE        ; BaseOfData
    dd IMAGE_BASE                ; ImageBase
    dd SECTION_ALIGNMENT        ; SectionAlignment
    dd FILE_ALIGNMENT            ; FileAlignment
    dw 4                        ; MajorOperatingSystemVersion
    dw 0                        ; MinorOperatingSystemVersion
    dw 0                        ; MajorImageVersion
    dw 0                        ; MinorImageVersion
    dw 4                        ; MajorSubsystemVersion
    dw 0                        ; MinorSubsystemVersion
    dd 0                        ; Win32VersionValue
;;    dd IMAGE_END - IMAGE_BASE    ; SizeOfImage
    dd (RAW_HEADER.SIZE + RAW_CODE.SIZE + RAW_DATA.SIZE)

    dd RAW_HEADER.SIZE          ; SizeOfHeaders
    dd 0                        ; CheckSum
    dw 2                        ; Subsystem
    dw 0                        ; DllCharacteristics
    dd 0x40000                  ; SizeOfStackReserve
    dd 0x6000                    ; SizeOfStackCommit
    dd 0x100000                  ; SizeOfHeapReserve
    dd 0x1000                    ; SizeOfHeapCommit
    dd 0                        ; LoaderFlags
    dd 16                        ; NumberOfRvaAndSizes
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_EXPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_IMPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_RESOURCE
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_EXCEPTION
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_SECURITY
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_BASERELOC
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_DEBUG
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_COPYRIGHT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_GLOBALPTR
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_TLS
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_IAT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT
dd 0, 0                      ; IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR
dd 0, 0                      ; reserved

optionalHeader.SIZE equ $ - optionalHeader

sectionHeaders:

    db ".text", 0, 0, 0          ; Name
    dd nagoa_round(RAW_CODE.SIZE) ; VirtualSize
    dd code                      ; VirtualAddress
    dd RAW_CODE.SIZE            ; SizeOfRawData
    dd RAW_CODE.OFFSET          ; PointerToRawData
    dd 0                        ; PointerToRelocations
    dd 0                        ; PointerToLinenumbers
    dw 0                        ; NumberOfRelocations
    dw 0                        ; NumberOfLinenumbers
    dd 0x60000020                ; Characteristics

    db ".data", 0, 0, 0          ; Name
    dd nagoa_round(RAW_DATA.SIZE) ; VirtualSize
    dd data                      ; VirtualAddress
    dd RAW_DATA.SIZE            ; SizeOfRawData
    dd RAW_DATA.OFFSET          ; PointerToRawData
    dd 0                        ; PointerToRelocations
    dd 0                        ; PointerToLinenumbers
    dw 0                        ; NumberOfRelocations
    dw 0                        ; NumberOfLinenumbers
    dd 0xC0000040                ; Characteristics

align FILE_ALIGNMENT, db 0

RAW_HEADER.SIZE equ $ - header

; ******************************************************************************************************

;;section .text vstart=nagoa_round($)

section .code

code:
entryPoint:

xor eax, eax
ret

align FILE_ALIGNMENT, db 0

RAW_CODE.OFFSET equ RAW_HEADER.SIZE
RAW_CODE.SIZE equ $ - code ;; $-$$ also gives the size of section .code

; ******************************************************************************************************

;;section .data vstart=nagoa_round($)

section .data

data:
db "An unused string"

align FILE_ALIGNMENT, db 0

RAW_DATA.OFFSET equ RAW_CODE.OFFSET + RAW_CODE.SIZE
RAW_DATA.SIZE equ $ - data ;; $-$$ also gives the size of section .data

; ******************************************************************************************************

;;IMAGE_END equ nagoa_round($)

IMAGE_END equ $

;; -- eof --
« Last Edit: July 14, 2013, 06:41:10 AM by Frank Kotler »

Offline Frank Kotler

  • NASM Developer
  • Hero Member
  • *****
  • Posts: 2667
  • Country: us
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #7 on: July 14, 2013, 06:44:14 AM »
Thanks Steve! I put "code tags" around your code to try to make it more readable - and easier to download. Hope I didn't screw it up!

Best,
Frank


Offline ;

  • Jr. Member
  • *
  • Posts: 9
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #8 on: July 17, 2013, 08:43:13 AM »
Hi.
Thanks both of you for your help !

@ Frank Kotler :

I agree at 100% with you, it is better, safer and makes more sense to keep the usual compilation process for tall-serious-projects, including linkage.
However for those tall-serious-projects, I prefer C++ instead of ASM.
I just want use NASM for extra-light-tiny tools, or so, this is why I would like to see if it is possible to get rid of anything but NASM itself for the compilation. =)



@ s_dubrovich :

The needs of a difference between those raw and virtual offsets are why I tried to use the "vstart" property, then now when I build "exetest3.nsm", some offsets and variables are wrong :
- "SizeOfImage" value became the raw file size (0x600), but according to the PE specification, it must be the virtual size when loaded in memory (0x3000) ;
- "code" label is located at 0x400200, it must be 0x401000 because of the required section alignment ;
- "data" label is located at 0x400400, it must be 0x402000 because of the required section alignment.

(There is another error with "e_lfanew" which is 0x3C instead of 0x40, but this one comes from my code, the line "dq 0, 0" has to be replaced by "dd 0, 0, 0, 0, 0")

Anyway thanks again, and have a nice day !
« Last Edit: July 17, 2013, 08:45:10 AM by ; »

Offline s_dubrovich

  • Jr. Member
  • *
  • Posts: 8
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #9 on: July 18, 2013, 03:27:52 AM »
===
If I understand correctly, then change the ALIGN statement from:
align FILE_ALIGNMENT, db 0
to:
align SECTION_ALIGNMENT, db 0
-Steve
====

Offline ;

  • Jr. Member
  • *
  • Posts: 9
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #10 on: July 18, 2013, 12:59:27 PM »
Okay, well... I really have problems to explain what I would like. ;D
I apologize for that.

If I write "align SECTION_ALIGNMENT, db 0", then the code segment will be placed at 0x401000. This fact is cool.
But if I open "exetest.bin" with an hex editor, the code segment would be placed at offset 0x1000 from the starting of the file, which is wrong.

I need a code located at 0x200 in the "exetest.bin", treated as if it where located at 0x401000 when running.

Here are the locations required :

Segment - Raw offset - Virtual address
header
0
0x400000
.code
0x200
0x401000
.data
0x400
0x402000

Where "Raw offset" is what we can see when hex-editing the binary file, and where "Virtual address" is the actual address when program is loaded in RAM by the windows PE loader.
How can I get this behavior ?

Is my text clean to understanding ? :/

Thank you for helping.
Sincerely.
;

Offline dogman

  • Jr. Member
  • *
  • Posts: 51
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #11 on: July 18, 2013, 01:32:17 PM »
If I understand what you are asking this is done by the linker and loader. You really don't want an executable to be 0x401000+ bytes long just so it can be loaded there. Each OS has its own way of mandating where stuff gets loaded.

With gas (probably not available under Windows but possibly is using cygwin) you can specify absolute locations but I haven't tried that for big location values. I used it to try to map a dynamic storage area beginning at 0 so I could use offsets to it. It works but it's ugly. The stuff gets assembled into an .absolute section iirc.

If you can get nasm to show you its symbol table and if you know where you program will always be loaded you can figure the rest out with a hex calculator.
« Last Edit: July 18, 2013, 01:38:38 PM by dogman »

Offline ;

  • Jr. Member
  • *
  • Posts: 9
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #12 on: July 18, 2013, 06:31:01 PM »
No of course, I never intended to have a so huge executable file. ;)
Is it so impossible to cause gaps between raw and virtual offsets under NASM ?

Each OS has its own way of mandating where stuff gets loaded.
This is not the case, at least for windows : each executable file must specify every location of its segments.
And nothing can be located at 0, microsoft define it as a reserved memory zone. The most common image base is 0x400000.

Offline s_dubrovich

  • Jr. Member
  • *
  • Posts: 8
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #13 on: July 19, 2013, 01:21:22 AM »
Okay, well... I really have problems to explain what I would like. ;D
I apologize for that.

If I write "align SECTION_ALIGNMENT, db 0", then the code segment will be placed at 0x401000. This fact is cool.
But if I open "exetest.bin" with an hex editor, the code segment would be placed at offset 0x1000 from the starting of the file, which is wrong.

I need a code located at 0x200 in the "exetest.bin", treated as if it where located at 0x401000 when running.

Here are the locations required :

Segment -    Raw offset -    Virtual address
header   
0
   
0x400000
.code   
0x200
   
0x401000
.data   
0x400
   
0x402000

Where "Raw offset" is what we can see when hex-editing the binary file, and where "Virtual address" is the actual address when program is loaded in RAM by the windows PE loader.
How can I get this behavior ?

Is my text clean to understanding ? :/

Thank you for helping.
Sincerely.
;

OK, revert alignment to:
align FILE_ALIGNMENT, db 0
;;align SECTION_ALIGNMENT, db 0

and set vstart= to:

section .code vstart=401000h

section .data vstart=402000h

SECTION .text already has the .. org IMAGE_BASE

So the map file gives:


---- Section .text ------------------------------------------------------------

Real              Virtual           Name
          400000            400000  header
          400040            400040  imageHeader
          400058            400058  optionalHeader
          400138            400138  sectionHeaders

---- Section .code ------------------------------------------------------------

Real              Virtual           Name
          400200            401000  code
          400200            401000  entryPoint

---- Section .data ------------------------------------------------------------

Real              Virtual           Name
          400400            402000  data
          400600            402200  IMAGE_END

Is that good??

hth,

Steve

I apologize for my poor editing skill.

Offline ;

  • Jr. Member
  • *
  • Posts: 9
Re: Dealing with virtual and raw addresses (avoid the use of the linker)
« Reply #14 on: July 19, 2013, 09:59:10 AM »
Yeah, this is exactly what I would like !
Thank you very much for brain tormenting yourself about my problem ! 8)

Yet it would have been cool if we could upgrade this code again.
Is it possible to do something like "vstart=nagoa_round($)" instead of "vstart=0x402000", in order to have a value automatically computed ?

Let's give you some examples :

______________________________________________________________________________________

Here is the current situation.
I added a "size" column in order to show the point :

Section - Raw file offset - Virtual address - Size
header
0
0x400000
0x188
.code
0x200
0x401000
3
.data
0x400
0x402000
16

______________________________________________________________________________________

What if the ".code" section grows ?
First case, this is when the section reaches a size greater than 0x200. The ".data" section becomes located at real offset "0x600", but can stay at virtual address "0x402000" :

Section - Raw file offset - Virtual address - Size
header
0
0x400000
0x188
.code
0x200
0x401000
0x203
.data
0x600
0x402000
16

______________________________________________________________________________________

Second case, when the ".code" section reaches a size greater than "0x1000", virtual address of ".data" must be updated too :

Section - Raw file offset - Virtual address - Size
header
0
0x400000
0x188
.code
0x200
0x401000
0x1003
.data
0x1300
0x403000
16

______________________________________________________________________________________

Yes this is very tricky, but this is the PE specification from Microsoft... -_-"

Unfortunately, "vstart=nagoa_round($)" send an error, as said previously in this topic.

;