functions/private/.segment.ps1
|
<#
.SYNOPSIS Defines a segment in the PSASM Assembler. .DESCRIPTION The .segment function adds a new segment to the assembler if it does not already exist. If the segment already exists, it sets it as the current segment and ignores any parameters. Segments define memory regions for code and data in the assembly process. .PARAMETER name The name of the segment. This parameter is mandatory. .PARAMETER Start The start address of the segment. If not specified, defaults to -1. Cannot be used together with StartAfter. .PARAMETER StartAfter The name of the segment after which this segment should start. Cannot be used together with Start. .PARAMETER End The end address of the segment. If not specified, defaults to -1. .PARAMETER Size The size of the segment in bytes. If not specified, defaults to -1. .PARAMETER Run The run address for the segment. Defaults to the Start address. .PARAMETER Align The alignment for the segment. Defaults to 0. .PARAMETER Fill Switch to indicate if the segment should be filled. .PARAMETER FillByte The byte value to use for filling the segment. Defaults to 0. .PARAMETER AllowOverlap Switch to allow overlapping with other segments. .PARAMETER Virtual Switch to mark the segment as virtual. .EXAMPLE .segment -name "code" -Start 0x1000 -End 0x1FFF Defines a segment named "code" starting at address 0x1000 and ending at 0x1FFF. .EXAMPLE .segment -name "data" -StartAfter "code" -Size 1024 -Fill -FillByte 0xFF Defines a segment named "data" starting after the "code" segment, with a size of 1024 bytes, filled with 0xFF. .NOTES This function is part of the PSASM Assembler. Parameter combinations are validated to prevent conflicts. #> function .segment { [PSASM()] param ( [Parameter(Mandatory)] [string]$name, [int]$Start = -1, [string]$StartAfter = $null, [int]$End = -1, [int]$Size = -1, [int]$Run = -1, [int]$Align = 0, [switch]$Fill = $false, [byte[]]$FillBytes = @(,0), [switch]$AllowOverlap = $false, [switch]$Virtual = $false ) if ($psasm.Segments.Segments.ContainsKey($name)) { ### Set current segment if already defined, ignoring parameters $extraParams = @('Start','StartAfter','End','Size','Run','Align','Fill','FillBytes','AllowOverlap','Virtual') | Where-Object { $PSBoundParameters.ContainsKey($_) } if ($extraParams.Count -gt 0) { # Write-Warning "Segment '$name' already defined. Ignoring parameters: $($extraParams -join ', ')" } } else { ### Add segment if not already defined $newSegment = [Segment]::New($name) if ($End -ge 0 -and $Size -ge 0 -and $Start -lt 0 -and -not $StartAfter) { # End and Size, but no Start or StartAfter $Start = $End - $Size + 1 } elseif ($Start -ge 0) { # Start specified if (-not $StartAfter) { if ($End -ge 0 -and $Size -ge 0) { throw "Cannot specify both End and Size when Start is specified for segment '$name'" } if ($End -ge 0) { $Size = $End - $Start + 1 } elseif ($Size -ge 0) { $End = $Start + $Size - 1 } else { # No End or Size - Should I throw? #throw "Must specify either End or Size when Start is specified for segment '$name'" } } else { throw "Cannot specify both Start and StartAfter for segment '$name'" } } elseif ($StartAfter) { if ($End -ge 0 -and $Size -ge 0) { throw "Cannot specify both End and Size when StartAfter is specified for segment '$name'" } } else { # No Start or StartAfter $Start = $psasm.Segments.Current.PC # throw "Must specify either Start or StartAfter for segment '$name'" } # if ($Align -lt 0 -and $End -lt 0) { # throw "Segment '$name' with negative Align requires either -End, -Start and -Size, or -StartAfter and -Size to be specified" # } $newSegment.StartAddress = $Start $newSegment.StartAfter = $StartAfter $newSegment.LastAddress = $End $newSegment.Size = $Size $newSegment.RunAddress = $Run #-lt 0 ? $Start : $Run $newSegment.Align = $Align $newSegment.Fill = $Fill.IsPresent $newSegment.FillBytes = $FillBytes $newSegment.AllowOverlap = $AllowOverlap.IsPresent $newSegment.Virtual = $Virtual.IsPresent $psasm.Segments.Add($newSegment) } $psasm.Segments.Set($name) } |